Clojure JIRAhttp://dev.clojure.org/jira/secure/IssueNavigator.jspa?reset=true&jqlQuery=project+%3D+CLJS+AND+resolution+%3D+Unresolved+AND+assignee+is+EMPTY+ORDER+BY+priority+DESC
An XML representation of a search requesten-us4.464925-07-2011[CLJS-1439] Add type annotations to goog-define defined varshttp://dev.clojure.org/jira/browse/CLJS-1439
ClojureScript<p>Currently it's still required to annotate <tt>goog-define</tt> constants with <tt>^boolean</tt> to allow the Closure compiler to safely remove dead branches. The macro could emit the var with <tt>^boolean</tt> metadata to make this unnecessary.</p>
<p>In general it would be nice to have similar annotations for the already defined constants like <tt>goog.DEBUG</tt> although I'm not sure how/if that's possible.</p>CLJS-1439Add type annotations to goog-define defined varsEnhancementMajorOpenUnresolvedUnassignedMartin KlepschTue, 1 Sep 2015 11:41:09 -0500Tue, 1 Sep 2015 11:48:08 -050001Global Rank[CLJS-365] apply needs to put all args after the 20th into an array seqhttp://dev.clojure.org/jira/browse/CLJS-365
ClojureScript<p>This ticket is related to <a href="http://dev.clojure.org/jira/browse/CLJS-359" title="`with-meta` does not work on function objects"><del>CLJS-359</del></a></p>CLJS-365apply needs to put all args after the 20th into an array seqDefectMajorOpenUnresolvedUnassignedDavid NolenWed, 29 Aug 2012 10:17:43 -0500Wed, 29 Aug 2012 20:36:00 -050001Global Rank[CLJS-364] compiler needs to put all args of an invocation after 20 into an array-seqhttp://dev.clojure.org/jira/browse/CLJS-364
ClojureScript<p>This ticket is related to <a href="http://dev.clojure.org/jira/browse/CLJS-359" title="`with-meta` does not work on function objects"><del>CLJS-359</del></a></p>CLJS-364compiler needs to put all args of an invocation after 20 into an array-seqDefectMajorOpenUnresolvedUnassignedDavid NolenWed, 29 Aug 2012 10:17:16 -0500Wed, 29 Aug 2012 20:35:42 -050001Global Rank[CLJS-1558] Code allowed to re-define referred varhttp://dev.clojure.org/jira/browse/CLJS-1558
ClojureScript<p>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. </p>
<p>FWIW, Clojure disallows this, and refuses to allow you to evaluate a def involving a referred var, and emits an error diagnostic like:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">CompilerException java.lang.IllegalStateException: foo already refers to: #'some.name.space/foo in namespace: user, compiling:(NO_SOURCE_PATH:2:1)</pre>
</div></div>
<p>Here is a complete example illustrating the issues:</p>
<p>Given:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns foo.core)
(defn square [x]
(* x x))</pre>
</div></div>
<p>then do this in a REPL:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">cljs.user=&gt; (require '[foo.core :refer [square]])
nil
cljs.user=&gt; (<span class="code-keyword">var</span> square)
#'foo.core/square
cljs.user=&gt; (square 3)
9
cljs.user=&gt; (ns-interns 'cljs.user)
{}
cljs.user=&gt; (defn square [x] (+ x x))
WARNING: square already refers to: foo.core/square being replaced by: cljs.user/square at line 1 &lt;cljs repl&gt;
#'foo.core/square
cljs.user=&gt; (square 3)
6
cljs.user=&gt; (<span class="code-keyword">var</span> square)
#'foo.core/square
cljs.user=&gt; (in-ns 'foo.core)
nil
foo.core=&gt; (square 3)
6
foo.core=&gt; (in-ns 'cljs.user)
nil
cljs.user=&gt; (ns-interns 'cljs.user)
{square #'cljs.user/square}
cljs.user=&gt; (cljs.user/square 3)
TypeError: Cannot read property 'call' of undefined
at repl:1:105
at repl:9:3
at repl:14:4
at <span class="code-object">Object</span>.exports.runInThisContext (vm.js:54:17)
at Domain.&lt;anonymous&gt; ([stdin]:41:34)
at Domain.run (domain.js:221:14)
at Socket.&lt;anonymous&gt; ([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=&gt; #'cljs.user/square
#'cljs.user/square
cljs.user=&gt; @#'cljs.user/square
nil</pre>
</div></div>CLJS-1558Code allowed to re-define referred varDefectMajorOpenUnresolvedUnassignedMike FikesSun, 31 Jan 2016 17:42:53 -0600Sun, 31 Jan 2016 17:42:53 -06001.7.22801Global Rank[CLJS-1479] Race condition in browser REPLhttp://dev.clojure.org/jira/browse/CLJS-1479
ClojureScript<p>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.</p>
<p>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".</p>
<p>Minimal setup:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(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 <span class="code-quote">"http:<span class="code-comment">//localhost:9000/repl"</span>)]
</span> {:output-to <span class="code-quote">"target/cljs-race/main.js"</span>
:output-dir <span class="code-quote">"target/cljs-race"</span>
:main 'race.repl})
(spit <span class="code-quote">"target/cljs-race/index.html"</span>
(str <span class="code-quote">"&lt;html&gt;"</span> <span class="code-quote">"&lt;body&gt;"</span>
<span class="code-quote">"&lt;script type=\"</span>text/javascript\<span class="code-quote">" src=\"</span>main.js\<span class="code-quote">"&gt;"</span>
<span class="code-quote">"&lt;/script&gt;"</span> <span class="code-quote">"&lt;/body&gt;"</span> <span class="code-quote">"&lt;/html&gt;"</span>))</pre>
</div></div>
<p>Now start the environment:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def env (browser/repl-env :<span class="code-keyword">static</span>-dir [<span class="code-quote">"target/cljs-race"</span> <span class="code-quote">"."</span>] :port 9000 :src nil))
(env/with-compiler-env (env/<span class="code-keyword">default</span>-compiler-env)
(repl/-setup env {}))</pre>
</div></div>
<p>cross your fingers and start this endless loop:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(loop [i 0]
(println (java.util.Date.) i)
(dotimes [j 100]
(let [result (repl/-evaluate env <span class="code-quote">"&lt;exec&gt;"</span> <span class="code-quote">"1"</span> <span class="code-quote">"<span class="code-keyword">true</span>"</span>)]
(when-not (= :success (:status result))
(println i j result))))
(recur (inc i)))</pre>
</div></div>
<p>To simulate heavy load run heavy-load.sh from attachment.</p>
<p>After some iterations (eg 55 big loop i) execution stops. If you investigate stacks (see race-condition.jstack), you can see in one thread:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">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)</pre>
</div></div>
<p>The code is waiting for a promise with a connection (which already did arive).</p>
<p>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.</p>
<p>Can somebody with better understanding of REPL internals investigate? Thank you.</p>CLJS-1479Race condition in browser REPLDefectMajorOpenUnresolvedUnassignedDaniel SkardaTue, 3 Nov 2015 10:13:04 -0600Fri, 12 Feb 2016 14:57:18 -06001.7.14500<p>A patch is welcome for this one.</p>Global Rank[CLJS-1691] spec internal compiler APIshttp://dev.clojure.org/jira/browse/CLJS-1691
ClojureScriptCLJS-1691spec internal compiler APIsTaskMajorOpenUnresolvedUnassignedDavid NolenTue, 21 Jun 2016 10:36:05 -0500Tue, 21 Jun 2016 10:36:05 -05001.9.7603Global Rank[CLJS-525] Allow hashtable lookup used for numbers and strings to be extended to other built-in typeshttp://dev.clojure.org/jira/browse/CLJS-525
ClojureScript<p>...which would enable safe extension of key cljs protocols to types without modifying their prototypes, e.g. <a href="http://dev.clojure.org/jira/browse/CLJS-523" title="IHash not extended to js/Date"><del>CLJS-523</del></a>.</p>CLJS-525Allow hashtable lookup used for numbers and strings to be extended to other built-in typesEnhancementMajorOpenUnresolvedUnassignedChas EmerickMon, 17 Jun 2013 13:59:52 -0500Mon, 17 Jun 2013 15:05:30 -050002<p>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?</p><p>instanceof or the ever-gruesome toString.call(aDate) == '<span class="error">&#91;object Date&#93;</span>' will work.</p>Global Rank[CLJS-1753] cljs.pprint does not print default tagged literals/elementshttp://dev.clojure.org/jira/browse/CLJS-1753
ClojureScript<p>Hi there!<br/>
I am having troubles making the cljs pretty print (cljs.pprint/pprint) behave the same way as the regular cljs or clj print function when it goes down to tagged elements that are by default used to denote custom records.</p>
<p>See example below - <b>pr, pr-str, print</b> and <b>print-str</b> functions all use the default approach toward creating (edn-like) tagged element for MyRecord and all produce the same result:<br/>
<b>#cljs.user.MyRecord{:value "a"}</b></p>
<p>On the other hand <b>pprint</b> just ignores the record's tag and simply just traverses/prints it as a map:<br/>
<b>{:value "a"}</b></p>
<p>Is there some setting and/or parameter in cljs.pprint namespace I am missing? I looked briefly at the code, but it seems it uses print-str by default - so maybe it just traverses the graph depth-first and does not check for every node's type? At this stage this seems like a bug to me as the expected behavior of the pprint function is that it would behave the same way print and other core functions do.</p>
<p>THIS WORKS:</p>
<blockquote>
<p>cljs.user=&gt; (defrecord MyRecord <span class="error">&#91;value&#93;</span>)<br/>
cljs.user/MyRecord<br/>
cljs.user=&gt; (pr (MyRecord. "a"))<br/>
#cljs.user.MyRecord{:value "a"}<br/>
nil<br/>
cljs.user=&gt; (pr-str (MyRecord. "a"))<br/>
"#cljs.user.MyRecord{:value \"a\"}"<br/>
cljs.user=&gt; (print (MyRecord. "a"))<br/>
#cljs.user.MyRecord{:value a}<br/>
nil<br/>
cljs.user=&gt; (print-str (MyRecord. "a"))<br/>
"#cljs.user.MyRecord{:value a}"</p></blockquote>
<p>BUT THIS DOESN'T:</p>
<blockquote>
<p>cljs.user=&gt; (cljs.pprint/pprint (MyRecord. "a"))<br/>
{:value "a"}<br/>
("{:value \"a\"}\n")<br/>
cljs.user=&gt; (with-out-str (cljs.pprint/pprint (MyRecord. "a")))<br/>
"{:value \"a\"}\n"</p></blockquote>
<p>According to github the head revision of the cljs.pprint namespace has not changed since 1.7.28 so I'd assume all versions up to the current one are affected.</p>
<p>Thanks for help!</p>Win 7 64bitCLJS-1753cljs.pprint does not print default tagged literals/elementsDefectMajorOpenUnresolvedUnassignedMiroslav KubicekbugTue, 16 Aug 2016 09:03:17 -0500Tue, 16 Aug 2016 09:03:17 -050000Global Rank[CLJS-1690] spec the ClojureScript ASThttp://dev.clojure.org/jira/browse/CLJS-1690
ClojureScriptCLJS-1690spec the ClojureScript ASTTaskMajorOpenUnresolvedUnassignedDavid NolenTue, 21 Jun 2016 10:35:40 -0500Tue, 21 Jun 2016 10:35:40 -05001.9.7603Global Rank[CLJS-1777] `module` undefined when using `:module-type :commonjs`http://dev.clojure.org/jira/browse/CLJS-1777
ClojureScript<p>The Google Closure Compiler support for CommonJS modules rewrites `exports` and `module.exports`, but not `module`. Many libraries try to detect the module type (CommonJS) by checking the type of `module`, e.g. this is taken from D3.</p>
<p>```<br/>
typeof exports === 'object' &amp;&amp; typeof module !== 'undefined'<br/>
```</p>
<p>This becomes</p>
<p>```<br/>
goog.provide('module$resource$d3')<br/>
typeof module$resource$d3 === 'object' &amp;&amp; typeof module !== 'undefined'<br/>
```</p>
<p>Because `module` is undefined this fails, and nothing gets exported.</p>
<p>This seems like something Google Closure should address.</p>
<p>Alternatives would include injecting some code that defines `module` (`var module={}`) or munging `typeof module` to `"object"`.</p>CLJS-1777`module` undefined when using `:module-type :commonjs`EnhancementMajorOpenUnresolvedUnassignedArne BrasseurWed, 14 Sep 2016 06:38:40 -0500Wed, 14 Sep 2016 09:04:00 -050000<p>To test</p>
<p> curl <a href="https://d3js.org/d3.v4.js">https://d3js.org/d3.v4.js</a> &gt; d3.js</p>
<p>Compiler options </p>
<p> :foreign-libs [{:file "d3.js"<br/>
:provides <span class="error">&#91;&quot;d3&quot;&#93;</span><br/>
:module-type :commonjs}]</p>
<p>Code</p>
<p> (:require '<span class="error">&#91;d3&#93;</span>)<br/>
(d3/select "#app")</p><p>Seems this exact case was already documented on Maria Geller's blog: <a href="http://mneise.github.io/posts/2015-07-08-week-6.html">http://mneise.github.io/posts/2015-07-08-week-6.html</a></p><p>Did some more digging, the issue is that thanks to <a href="http://dev.clojure.org/jira/browse/CLJS-1312">http://dev.clojure.org/jira/browse/CLJS-1312</a> Closure Compiler tries to deal with UMD syntax, but there's no single definition of what UMD really looks like. Two popular tools (rollup and webpack) generate code that is not correctly recognized. This is what rollup generates</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript">(<span class="code-keyword">function</span> (global, factory) {
<span class="code-keyword">typeof</span> exports === 'object' &amp;&amp; <span class="code-keyword">typeof</span> module !== 'undefined' ? factory(exports) :
<span class="code-keyword">typeof</span> define === '<span class="code-keyword">function</span>' &amp;&amp; define.amd ? define(['exports'], factory) :
(factory((global.d3 = global.d3 || {})));
}(<span class="code-keyword">this</span>, (<span class="code-keyword">function</span> (exports) { 'use strict';</pre>
</div></div>
<p>This is what webpack generates</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript">(<span class="code-keyword">function</span> webpackUniversalModuleDefinition(root, factory) {
<span class="code-keyword">if</span>(<span class="code-keyword">typeof</span> exports === 'object' &amp;&amp; <span class="code-keyword">typeof</span> module === 'object')
module.exports = factory(require("react"), require("react-dom"));
<span class="code-keyword">else</span> <span class="code-keyword">if</span>(<span class="code-keyword">typeof</span> define === '<span class="code-keyword">function</span>' &amp;&amp; define.amd)
define(["react", "react-dom"], factory);
<span class="code-keyword">else</span> <span class="code-keyword">if</span>(<span class="code-keyword">typeof</span> exports === 'object')
exports["ReactDataGrid"] = factory(require("react"), require("react-dom"));
<span class="code-keyword">else</span>
root["ReactDataGrid"] = factory(root["React"], root["ReactDOM"]);
})(<span class="code-keyword">this</span>, <span class="code-keyword">function</span>(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE</pre>
</div></div>
<p>This will require changes to ProcessCommonJSModulesTest, similar to <a href="https://github.com/google/closure-compiler/commit/aa0a99cf380b05b2185156735d023b6fa78ec4ac">https://github.com/google/closure-compiler/commit/aa0a99cf380b05b2185156735d023b6fa78ec4ac</a></p>Global Rank[CLJS-1706] cljs.reader support for namespaced map literalhttp://dev.clojure.org/jira/browse/CLJS-1706
ClojureScript<p>Clojure 1.9 extends support for namespaced maps and <tt>cljs.reader</tt> needs to be able to read them.</p>
<p><tt>#:example{:key "value"</tt>} currently results in a <tt>Could not find tag parser for :example in ...</tt> error.</p>CLJS-1706cljs.reader support for namespaced map literalDefectMajorOpenUnresolvedUnassignedThomas HellerFri, 15 Jul 2016 08:24:33 -0500Thu, 11 Aug 2016 14:26:44 -050012<p>I wanted to start implementing this and started looking at the "spec" <span class="error">&#91;1&#93;</span>. It mentions support for <tt>#::</tt> and <tt>#::alias</tt>, but since <tt>cljs.reader</tt> does not have access to aliases (or the current ns) I do not know how to proceed. Should it just throw then encountering <tt>#::</tt> since it isn't really all that useful in a EDN context?</p>
<p><a href="http://dev.clojure.org/jira/browse/CLJ-1910">http://dev.clojure.org/jira/browse/CLJ-1910</a></p><p>What does the Clojure EDN reader do here?</p><p>The clojure.edn-reader seems to catch that it doesn't have a default namespace, nor any aliases.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-none">user&gt; (clojure.edn/read-string "#:a {:b 1}")
{:a/b 1}
user&gt; (clojure.edn/read-string "#::a {:b 1}")
RuntimeException Namespaced map must specify a valid namespace: :a clojure.lang.EdnReader$NamespaceMapReader.invoke (EdnReader.java:494)
user&gt; (clojure.edn/read-string "#:: {:b 1}")
RuntimeException Invalid token: : clojure.lang.Util.runtimeException (Util.java:221)</pre>
</div></div>
<p>This seems to be sane defaults also for cljs.reader.</p>
<p>Also see <a href="https://github.com/clojure/clojure/commit/6d48ae372a540903173be2974b66b8911371e05d#diff-3a5dca122734225f3f60263876401aebR605">the commit adding namespaces maps in clojure</a></p>Global Rank[CLJS-1823] read-string on map with multiple keys should throw errorhttp://dev.clojure.org/jira/browse/CLJS-1823
ClojureScript<p>On an array-map sized string `(read-string "{:a 1 :b 2 :a 1}")` returns a map with 2 :a keys.<br/>
On a hash-map sized string with duplicates no error is thrown.</p>
<p>Both of these cases deviate from Clojure's behaviour which is to throw a duplicate key exception.</p>CLJS-1823read-string on map with multiple keys should throw errorDefectMajorOpenUnresolvedUnassignedThomas MulvaneySat, 15 Oct 2016 10:30:35 -0500Mon, 17 Oct 2016 05:05:39 -050002<p>I am attaching a patch which makes the behaviour of reading a <tt>PersistentArrayMap</tt> same as <tt>PersistentHashMap</tt>. Now the duplicates are removed from <tt>PersistentArrayMap</tt>.</p>
<p>Both however don't throw an error.</p><p>I have attached an alternative patch which throws on duplicate when reading and handles other duplicate cases as per clojure. The extra cases which were not handled correctly previously have been added as tests.</p>Global Rank[CLJS-1829] 3-arity get does not return not-found on negative key values for arrays and stringshttp://dev.clojure.org/jira/browse/CLJS-1829
ClojureScript<p>Examples of failing cases:</p>
<p>Calling `(get "asd" -1 :not-found)` returns nil rather than :not-found.<br/>
Calling `(get #js <span class="error">&#91;1 2 3&#93;</span> -1 :not-found)` returns nil rather than :not-found.</p>CLJS-18293-arity get does not return not-found on negative key values for arrays and stringsDefectMajorOpenUnresolvedUnassignedThomas MulvaneyFri, 21 Oct 2016 04:32:50 -0500Fri, 21 Oct 2016 05:50:40 -050001<p>Good catch. Probably related to <a href="https://github.com/clojure/clojurescript/commit/9cb8da1d82078cfe21c7f732d94115867f455a0a">https://github.com/clojure/clojurescript/commit/9cb8da1d82078cfe21c7f732d94115867f455a0a</a></p>
<p>Mind if I work on this?</p><p>The attached patch also catches the case where a key is nil. Also using charAt rather than aget for strings.</p><p>Sorry António, I just saw your comment.</p>Global RankPatchCode and Test[CLJS-1833] Consider moving int behavior to unchecked-int + clearer docstrings for limitations of other coercions (long etc)http://dev.clojure.org/jira/browse/CLJS-1833
ClojureScriptCLJS-1833Consider moving int behavior to unchecked-int + clearer docstrings for limitations of other coercions (long etc)TaskMajorOpenUnresolvedUnassignedDavid NolenSun, 23 Oct 2016 10:03:49 -0500Sun, 23 Oct 2016 10:03:49 -050000Global Rank[CLJS-1410] Support source maps in deps.cljshttp://dev.clojure.org/jira/browse/CLJS-1410
ClojureScript<p>There should be support to package source maps with a foreign-lib using <tt>deps.cljs</tt></p>CLJS-1410Support source maps in deps.cljsEnhancementMajorOpenUnresolvedUnassignedMartin KlepschSun, 9 Aug 2015 13:49:35 -0500Fri, 12 Feb 2016 15:00:27 -060021<p>Patch welcome for this one!</p>Global Rank[CLJS-1836] nth doesn't throw for IndexedSeqshttp://dev.clojure.org/jira/browse/CLJS-1836
ClojureScript<p>Examples:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(nth (seq (array 0 1 2 3)) 4) =&gt; nil (expected js/Error)
(nth (seq (array 0 1 2 3)) -1) =&gt; nil (expected js/Error)
(nth (seq [0 1 2 3]) 4 :not-found) =&gt; nil (expected :not-found)
(nth (seq [0 1 2 3]) -1 :not-found) =&gt; nil (expected :not-found)
</pre>
</div></div>
<p>This only affects sequences of javascript arrays, strings and small (&lt;= 32 elements) PersistentVectors.</p>CLJS-1836nth doesn't throw for IndexedSeqsDefectMajorOpenUnresolvedUnassignedThomas MulvaneyTue, 25 Oct 2016 14:57:44 -0500Tue, 25 Oct 2016 14:59:15 -050001Global RankPatchCode and Test[CLJS-1447] IFn implementors have a broken call implementation, all args after 20th argument should be collected into a seqhttp://dev.clojure.org/jira/browse/CLJS-1447
ClojureScript<p>Regular fns (which are just JavaScript fns) have no such limit. For IFn implementors we should not allow arities above 21 args, and we should transform the 21st arity into a var args signature.</p>CLJS-1447IFn implementors have a broken call implementation, all args after 20th argument should be collected into a seqTaskMajorOpenUnresolvedUnassignedDavid NolenFri, 11 Sep 2015 16:31:31 -0500Tue, 8 Nov 2016 14:14:33 -06001.7.145Next00<blockquote><p>we should transform the 21st arity into a var args signature</p></blockquote>
<p>Unless misunderstanding, can't do that. Var args sigs aren't allowed in protocols.</p>
<blockquote><p>we should not allow arities above 21 args</p></blockquote>
<p>Emitting an analyzer warning is what you want? </p><p>I believe I hit this problem in my code using core.async<span class="error">&#91;1&#93;</span>.</p>
<p>If it is not possible to implement ATM, I would kindly ask for a compiler warning at least. This thing manifested as a infinite recursive loop ending up in a cryptic stack overflow.</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://github.com/binaryage/dirac/commit/cce56470975a287c0164e6f79cd525d6ed27a543">https://github.com/binaryage/dirac/commit/cce56470975a287c0164e6f79cd525d6ed27a543</a></p>Global Rank[CLJS-1446] autodoc + gh-pages for cljs.*.api namespaceshttp://dev.clojure.org/jira/browse/CLJS-1446
ClojureScriptCLJS-1446autodoc + gh-pages for cljs.*.api namespacesTaskMajorOpenUnresolvedUnassignedDavid NolennewbieFri, 11 Sep 2015 14:07:59 -0500Tue, 8 Nov 2016 14:14:33 -06001.7.145Next02<p>I just tried to get this working - unfortunately, autodoc doesn't currently have support for ClojureScript. An issue is currently open on the GH project <a href="https://github.com/tomfaulhaber/autodoc/issues/16">here</a> but it doesn't look like it's seen any movement in nearly two years.</p><p>I would love to see this work as well and, as the author of autodoc, am happy to help move it forward. I've added some commentary to the <a href="https://github.com/tomfaulhaber/autodoc/issues/16">issue in autodoc</a> about how to do this. If it's going to happen soon, though, I will need some help from the ClojureScript community as outlined over there.</p><p>This ticket is about generating docs for <b>Clojure</b> code. Getting autodoc to work for ClojureScript files is worth pursuing but unrelated to this ticket.</p><p>I took at stab at <a href="http://bensu.github.io/clojurescript-docs/">this</a> and only got it running using <tt>autodoc-0.9.0-standalone.jar</tt> from the command line. My results are not useful at all but those issues should be sorted out in autodoc.</p>
<p>David, do you have a preference in how the docs and artifacts needed should be managed? Should it be a lein plugin or can it be a script that assumes that the correct jars have been installed?</p><p>Oh, I did misunderstand this and then didn't see <span class="nobr"><a href="http://dev.clojure.org/jira/secure/ViewProfile.jspa?name=dnolen" class="user-hover" rel="dnolen"><sup><img class="rendericon" src="http://dev.clojure.org/jira/images/icons/user_12.gif" height="12" width="12" align="absmiddle" alt="" border="0"/></sup>David Nolen</a></span>'s follow-up until now. Let me take a look at whether I can make this happen pretty easily. I wouldn't think it would be too difficult. (Famous last words!)</p><p>I have just closed the blocking issue in autodoc <a href="https://github.com/tomfaulhaber/autodoc/issues/21">Issue 21</a>, and<span class="nobr"><a href="http://dev.clojure.org/jira/secure/ViewProfile.jspa?name=bensu" class="user-hover" rel="bensu"><sup><img class="rendericon" src="http://dev.clojure.org/jira/images/icons/user_12.gif" height="12" width="12" align="absmiddle" alt="" border="0"/></sup>Sebastian Bensusan</a></span> has successfully built a version of doc for the src/main/clojure/... stuff.</p>
<p>The next step is to flesh out what we want to push to <a href="http://clojure.github.io/clojurescript">http://clojure.github.io/clojurescript</a>. I don't think that this is too hard. Then we can integrate it with the autodoc robot and get automatic updates.</p>Global Rank[CLJS-1443] ES6 Module Processing at individual :foreign-lib spechttp://dev.clojure.org/jira/browse/CLJS-1443
ClojureScript<p>ES6 module processing could probably benefit from processing at the individual <tt>:foreign-lib</tt> spec. Brings up questions wrt. source maps and merged source maps when applying other optimization settings.</p>CLJS-1443ES6 Module Processing at individual :foreign-lib specEnhancementMajorOpenUnresolvedUnassignedDavid NolenWed, 9 Sep 2015 17:30:24 -0500Tue, 8 Nov 2016 14:14:33 -06001.7.145Next00Global Rank[CLJS-1402] Source Mapping Closure Error Loggerhttp://dev.clojure.org/jira/browse/CLJS-1402
ClojureScript<p>Current error reports generated by Google Closure point back to the generated JavaScript sources. For JavaScript source that originated from ClojureScript we should generated source mapped reports.</p>CLJS-1402Source Mapping Closure Error LoggerEnhancementMajorOpenUnresolvedUnassignedDavid Nolentype-checkSat, 8 Aug 2015 11:18:52 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next02Global Rank[CLJS-1373] Generalize CLJS-1324, check invokes of all IFn implementorshttp://dev.clojure.org/jira/browse/CLJS-1373
ClojureScript<p>We currently track all <tt>IFn</tt> implementors but in order to do arity checking of statically analyzeable invokes of keywords, vector, etc. we need to do a bit more. <tt>extend-type</tt> should update the type in the compiler state with <tt>:method-params</tt> <tt>:max-fixed-arity</tt> and <tt>:variadic</tt>. Then we can just reuse the existing checks in <tt>cljs.analyzer/parse-invoke</tt>.</p>CLJS-1373Generalize CLJS-1324, check invokes of all IFn implementorsEnhancementMajorOpenUnresolvedUnassignedDavid NolenTue, 28 Jul 2015 09:13:33 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next00Global Rank[CLJS-1328] Support defrecord reader tagshttp://dev.clojure.org/jira/browse/CLJS-1328
ClojureScript<p>Currently, defrecord instances print similar to how they do in clojure</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">&gt; (pr-str (garden.units/px 5))
#garden.types.CSSUnit{:unit :px, :magnitude 5}</pre>
</div></div>
<p>This representation cannot be read by the compiler, nor at runtime by cljs.reader/read-string</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">&gt; #garden.types.CSSUnit{:unit :px, :magnitude 5}
clojure.lang.ExceptionInfo: garden.types.CSSUnit {:type :reader-exception, :line 1, :column 22, :file <span class="code-quote">"NO_SOURCE_FILE"</span>}
...
&gt; (cljs.reader/read-string <span class="code-quote">"#garden.types.CSSUnit{:unit :px, :magnitude 5}"</span>)
#&lt;Error: Could not find tag parser <span class="code-keyword">for</span> garden.types.CSSUnit in (<span class="code-quote">"inst"</span> <span class="code-quote">"uuid"</span> <span class="code-quote">"queue"</span> <span class="code-quote">"js"</span>)&gt;
...</pre>
</div></div>
<h2><a name="Analysis"></a>Analysis</h2>
<p>The two requirements - using record literals in cljs source code and supporting runtime reading - can be addressed by using the analyzer to find defrecords and registering them with the two respective reader libraries.</p>
<h3><a name="Recordliterals"></a>Record literals</h3>
<p>Since clojurescript reads and compiles a file at a time, clojure's behavior for literals is hard to exactly mimic. That is, to be able to use the literal in the same file where the record is defined.<br/>
A reasonable compromise might be to update the record tag table after each file has been analyzed. Thus the literal form of a record could be used only in requiring files.</p>
<p><b>EDIT:</b> Record literals can also go into the constant pool</p>
<h3><a name="cljs.reader"></a>cljs.reader</h3>
<p>To play well with minification, the ^:export annotation could be reused on defrecords, to publish the corresponding reader tag to cljs.reader.</p>
<h2><a name="RelatedTickets"></a>Related Tickets</h2>
<ul class="alternate" type="square">
<li>Reusing the ^:export annotation interacts with <a href="http://dev.clojure.org/jira/browse/CLJS-1109">http://dev.clojure.org/jira/browse/CLJS-1109</a></li>
<li>data_readers.cljc support <a href="http://dev.clojure.org/jira/browse/CLJS-1194">http://dev.clojure.org/jira/browse/CLJS-1194</a> and <a href="http://dev.clojure.org/jira/browse/CLJS-335">http://dev.clojure.org/jira/browse/CLJS-335</a></li>
</ul>
CLJS-1328Support defrecord reader tagsEnhancementMajorOpenUnresolvedUnassignedHerwig HochleitnerreaderreadertagsSat, 4 Jul 2015 07:39:50 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next11<p>It's preferred that we avoid exporting. Instead we can adopt the same approach as the constant literal optimization for keywords under advanced optimizations. We can make a lookup table (which won't pollute the global namespace like exporting does) which maps a string to its type.</p>
<p>I'm all for this enhancement.</p>Global Rank[CLJS-1147] reconnect logic for browser REPLshttp://dev.clojure.org/jira/browse/CLJS-1147
ClojureScript<p>Instead of forcing users to refresh browser and lose application state, the browser REPL should poll once a second to connect if connection is unreachable for some reason.</p>CLJS-1147reconnect logic for browser REPLsEnhancementMajorOpenUnresolvedUnassignedDavid NolenWed, 18 Mar 2015 21:13:06 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next00<p>This is firmly a major nice-to-have, but not a blocker.</p>Global Rank[CLJS-1141] memoization of js-dependency-index and get-upstream-deps needs knobshttp://dev.clojure.org/jira/browse/CLJS-1141
ClojureScript<p>knobs should be exposed for more dynamic compilation environments like Figwheel which may desire to add dependencies to the classpath on the fly.</p>CLJS-1141memoization of js-dependency-index and get-upstream-deps needs knobsEnhancementMajorOpenUnresolvedUnassignedDavid NolenWed, 18 Mar 2015 00:05:41 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next01<p>A patch that caches upstream dependencies in the compiler env.</p><p>Actually I'm going to submit another patch that includes the memoize calls in js-deps.</p><p>New patch that moves <tt>cljs.js-deps</tt> memoization to current <tt>env/<b>compiler</b></tt> as well as <tt>get-upstream-deps</tt>.</p>
<p>Unfortunately there is a circular dep between <tt>cljs.env</tt> and <tt>cljs.js-deps</tt>, if we want to cache in <tt>env/<b>compiler</b></tt>. I overcame this with a resolve.</p>
<p>Compile performance is either completely unchanged or slightly improved based on several test runs.</p>
<p>Hold off on this. Its not behaving as expected. Doesn't seem to be caching in certain situations.</p><p>Thanks for the update. This will definitely not land until after the pending REPL/piggieback release anyhow.</p><p>Yeah there is an obvious bug and a subtle one. Hopefully will finish it up soonish.</p><p>Alright, this latest patch works. There was a subtle memoizing nil value bug.</p>Global Rank[CLJS-712] resolve-var for symbol with dot still wronghttp://dev.clojure.org/jira/browse/CLJS-712
ClojureScript<p>We need to recur on the first segment passing an new additional argument to resolve-var indicating that we should not try to resolve in the current namespace and instead warn.</p>CLJS-712resolve-var for symbol with dot still wrongDefectMajorOpenUnresolvedUnassignedDavid NolenTue, 3 Dec 2013 21:09:53 -0600Tue, 8 Nov 2016 14:14:36 -06001.7.145Next00Global Rank[CLJS-1693] rel-output-path produces wrong path for :lib fileshttp://dev.clojure.org/jira/browse/CLJS-1693
ClojureScript<p>Building with a cljsjs package where cljsjs package includes <tt>:libs</tt> in <tt>deps.cljs</tt> you find the "out" directory includes a subdirectory "file:".</p>
<p>An example from my specific case:<br/>
"out/<a href="file:/home/vagrant/.m2/repository/cljsjs/openlayers/3.3.0-0/openlayers-3.3.0-0.jar!/cljsjs/development/openlayers/ol/array.js">file:/home/vagrant/.m2/repository/cljsjs/openlayers/3.3.0-0/openlayers-3.3.0-0.jar!/cljsjs/development/openlayers/ol/array.js</a>"</p>
<p>':' is not permitted on Windows filesystem, which leads to compilation error.</p>
<p>It happens because <tt>rel-output-path</tt> here <a href="https://github.com/clojure/clojurescript/blob/17bcf2a091accb6f7caf1e8fa3954b490e9d34fa/src/main/clojure/cljs/closure.clj#L1515">https://github.com/clojure/clojurescript/blob/17bcf2a091accb6f7caf1e8fa3954b490e9d34fa/src/main/clojure/cljs/closure.clj#L1515</a> detects closure-lib first (before taking in account that it is in jar) and passes it to <tt>lib-rel-path</tt> which acts as if file is located in project directory.</p>
<p>Another issue, but deeply related, is that on Windows, <tt>lib-rel-path</tt> breaks build even for <tt>:lib</tt> files located in project directory. It happens because of naive path prefix removal <a href="https://github.com/clojure/clojurescript/blob/17bcf2a091accb6f7caf1e8fa3954b490e9d34fa/src/main/clojure/cljs/closure.clj#L1500">https://github.com/clojure/clojurescript/blob/17bcf2a091accb6f7caf1e8fa3954b490e9d34fa/src/main/clojure/cljs/closure.clj#L1500</a> because it tries to remove a subpath with native path separators, but path comes here in url-like form with forward slashes. Compiler then reports that path is not relative and aborts compilation.</p>Bug presents in any environment, but break things only on Windows.CLJS-1693rel-output-path produces wrong path for :lib filesDefectMajorOpenUnresolvedUnassignedRuslan ProkopchukSat, 25 Jun 2016 00:15:06 -0500Sat, 25 Jun 2016 00:15:06 -05001.9.7612Global Rank[CLJS-1806] build api fails to generate inline code for :target :nodejshttp://dev.clojure.org/jira/browse/CLJS-1806
ClojureScript<p>when inline code is provided as vector to the composition of `cljs.build.api/build` and `cljs.build.api/inputs` methods under `:target :nodejs` the provided inline code is not output.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;; <span class="code-keyword">this</span> outputs code
(cljs.build.api/build (cljs.build.api/inputs '[(ns hello.core) (+ 1 2)]) {})
;; <span class="code-keyword">this</span> does not output inline code
(cljs.build.api/build (cljs.build.api/inputs '[(ns hello.core) (+ 1 2)]) {:target :nodejs})
;; When you don't use cljs.build.api/inputs everything works correctly
(cljs.build.api/build '[(ns hello.core) (+ 1 2)] {}) ;; <span class="code-keyword">this</span> outputs code
(cljs.build.api/build '[(ns hello.core) (+ 1 2)] {:target :nodejs}) ;; <span class="code-keyword">this</span> outputs code</pre>
</div></div>CLJS-1806build api fails to generate inline code for :target :nodejsDefectMajorOpenUnresolvedUnassignedBruce HaumanSat, 1 Oct 2016 12:51:26 -0500Sun, 30 Oct 2016 11:31:50 -05001.9.7612<p>From @ykomatsu on Github:</p>
<p>add-preloads seems to remove cljs/nodejs.cljs.</p>
<p><a href="https://github.com/clojure/clojurescript/blob/ab7a4911f1fd3a81210b1a9f2d84857748f8268b/src/main/clojure/cljs/closure.clj#L897">https://github.com/clojure/clojurescript/blob/ab7a4911f1fd3a81210b1a9f2d84857748f8268b/src/main/clojure/cljs/closure.clj#L897</a></p>
<p>This patch will fix this problem but I am not sure if this is correct solution.</p>
<p><a href="https://github.com/ykomatsu/clojurescript/commit/fc986467e66e6a628dc8f0e8a2ef2b30f715fd23">https://github.com/ykomatsu/clojurescript/commit/fc986467e66e6a628dc8f0e8a2ef2b30f715fd23</a></p>
Global Rank[CLJS-1297] defrecord does not emit IKVReduce protocolhttp://dev.clojure.org/jira/browse/CLJS-1297
ClojureScript<p>Records are maps and in Clojure they support reduce-kv (IKVReduce protocol).<br/>
This is not true in ClojureScript:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defrecord Foobar [x y])
(reduce-kv assoc {} (Foobar. 1 2))</pre>
</div></div>
<p>Fails wit Error: No protocol method IKVReduce.-kv-reduce defined for type : <span class="error">&#91;object Object&#93;</span></p>CLJS-1297defrecord does not emit IKVReduce protocolDefectMajorOpenUnresolvedUnassignedDaniel SkardanewbieWed, 3 Jun 2015 15:54:04 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next04<p>Just seems like an oversight. Patch welcome, this one is a relatively easy one.</p><p>OK <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/></p>
<p>I checked Clojure implementation. Records do not implement any reduce protocol on their own. For IKVReduce records use default implementation using reduce and destructuring. Is this approach OK?</p>
<p>Recently Alex Miller implemented many optimizations of reduce protocols in Clojure. Eg range returns an object which implements IReduce protocol so reduce (and transducers in general) can take advantage of it. Any plans for such optimizations in ClojureScript? </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;;clojure/src/clj/clojure/core.clj:6523
;;slow path <span class="code-keyword">default</span>
clojure.lang.IPersistentMap
(kv-reduce
[amap f init]
(reduce (fn [ret [k v]] (f ret k v)) init amap))</pre>
</div></div>
<p>Going with the Clojure implementation is fine. Yes all of the optimizations in 1.7.0 are on the table for ClojureScript but these are separate issues from this one.</p><p>Mind if I take this as my first cljs bug? Poking around quickly I think I know what needs to happen.</p><p>Sure! Have you submitted your CA yet?</p><p>Yes, I did yesterday.</p><p>Here is a potential patch. I implemented a basic IKVreduce based on Daniel Skarda's comment. Note: I am a little fuzzy on macros still so please look over what I have. There is probably a better way<img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/help_16.gif" height="16" width="16" align="absmiddle" alt="" border="0"/>. Also added a test for reduce-kv on records.</p>
<p>I ran the test on Linux on V8 and SpiderMonkey. I plan to get JSC and Nashorn working and tested this week but if someone wants to test them out before that would be great.</p>
<p>Experience report:</p>
<p>I just tested the patch in the Node Repl and it seems to work:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">cljs.user=&gt; (defrecord A [a b])
cljs.user/A
cljs.user=&gt; (reduce-kv (fn [m k v] (assoc m k (inc v))) {} (A. 1 2))
{:a 2, :b 3}</pre>
</div></div>
<p>and the provided tests passed in Spidermonkey, V8, and Nashorn (I don't have JSC installed).</p>
<p>For completeness: before applying the patch the same code fails with:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Error: No protocol method IKVReduce.-kv-reduce defined <span class="code-keyword">for</span> type : [object <span class="code-object">Object</span>]</pre>
</div></div><p>Is this the same approach taken by Clojure?</p><p>You can see the relevant current Clojure code here...<br/>
<a href="https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6526">https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6526</a><br/>
I think it is the same. I literally just tried to translate it over into CLJS. I might of understood something wrong though.</p><p>Yes that's the slow path. Please use the implementation used by defrecord instead. If defrecord doesn't have one then this patch is OK.</p><p>As far as I can tell there is no implementation on defrecord itself however there are separate implementations on the the java classes PersistentVector, PersistentArrayMap, PersistentTreeMap, and PersistenHashMap in pure java. I am not sure if you would want to do something similar for Clojurescript.</p>
<p>I can also spend some time trying to make a more performant version.</p><p>Confirmed that Clojure uses the slow path via the IPersistentMap implementation in defrecord<br/>
<a href="https://github.com/clojure/clojure/blob/d920ad/src/clj/clojure/core.clj#L6712">https://github.com/clojure/clojure/blob/d920ad/src/clj/clojure/core.clj#L6712</a></p>
<p>Patch still applies and can also confirm it works for me.</p>Global Rank[CLJS-1813] bring clojure.core.specs from clojurehttp://dev.clojure.org/jira/browse/CLJS-1813
ClojureScript<p>In clojure there is clojure.core.specs namespace.<br/>
It has not yet be ported in clojurescript.</p>CLJS-1813bring clojure.core.specs from clojureEnhancementMajorOpenUnresolvedUnassignedYehonathan SharvitspecThu, 6 Oct 2016 12:36:52 -0500Thu, 6 Oct 2016 12:36:52 -05001.9.7602Global Rank[CLJS-338] Incorrect implementation of IReduce by ArrayChunkhttp://dev.clojure.org/jira/browse/CLJS-338
ClojureScript<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(reduce + (array-chunk (array 1 2 3 4) 1 3)) =&gt; 2 (instead of 5)
(reduce + 0 (array-chunk (array 1 2 3 4) 1 3)) =&gt; 3 (instead of 5)
(reduce + (array-chunk (array 1 2 3 4) 1 1)) =&gt; 2 (instead of 0)</pre>
</div></div>
<p>In src/cljs/cljs/core.cljs, line #1817:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(deftype ArrayChunk [arr off end]
;; ...
IReduce
(-reduce [coll f]
(ci-reduce coll f (aget arr off) (inc off))) ;; should be (<span class="code-keyword">if</span> (&lt; 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)</pre>
</div></div>CLJS-338Incorrect implementation of IReduce by ArrayChunkDefectMinorOpenUnresolvedUnassignedAnton FrolovbugSun, 22 Jul 2012 02:48:09 -0500Mon, 29 Jul 2013 23:36:08 -050001<p>Thanks for the report. ArrayChunk is an implementation detail - do these conditions actually arise?</p>Global Rank[CLJS-650] Optimize all protocolshttp://dev.clojure.org/jira/browse/CLJS-650
ClojureScript<p>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.</p>
<p>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.</p>CLJS-650Optimize all protocolsEnhancementMinorOpenUnresolvedUnassignedDavid NolenFri, 1 Nov 2013 12:24:49 -0500Fri, 1 Nov 2013 12:25:08 -050000Global Rank[CLJS-720] #queue literal behavior is incorrecthttp://dev.clojure.org/jira/browse/CLJS-720
ClojureScript<p>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.</p>CLJS-720#queue literal behavior is incorrectDefectMinorOpenUnresolvedUnassignedDavid NolenSat, 7 Dec 2013 21:20:49 -0600Sat, 7 Dec 2013 21:20:49 -060000Global Rank[CLJS-736] Functions folder and reducer broken for types nil and array + fix for typohttp://dev.clojure.org/jira/browse/CLJS-736
ClojureScript<p>1. This currently doesn't work:</p>
<p>(-&gt;&gt; nil<br/>
(r/map identity)<br/>
(r/reduce + 0))<br/>
; org.mozilla.javascript.JavaScriptException: Error: No protocol method IReduce.-reduce defined for type null</p>
<p>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.</p>
<p>2. An entirely analogous problem exists for collections of type array.</p>
<p>3. The patch <a href="http://dev.clojure.org/jira/browse/CLJS-700" title="clojure.core.reducers/fold broken"><del>CLJS-700</del></a> mistakenly defined coll-fold for the type cljs.core/IPersistentVector. This should have been cljs.core/PersistentVector. (There exists no protocol IPersistentVector in ClojureScript.)</p>
<p>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.</p>CLJS-736Functions folder and reducer broken for types nil and array + fix for typoDefectMinorOpenUnresolvedUnassignedJonas De VuystSun, 29 Dec 2013 10:27:20 -0600Tue, 2 Dec 2014 08:26:25 -060002<p>Alternative patch in which r/reduce and r/fold treat arrays and nil as special cases &#8211; as opposed to having arrays and nil implement IReduce and CollFold.</p>
<p>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.</p>
<p>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.</p><p>The <tt>implements?</tt> should probably be a <tt>satisfies?</tt> in the second patch. Have you run any benchmarks of before/after the patch?</p><p>If I understand correctly then <tt>(satisfies? x y)</tt> is roughly equivalent to <tt>(or (implements? x y) (natively-satisfies? x y))</tt>.</p>
<p>If native types (nil, array, object currently) are treated as special cases then <tt>implements?</tt> seems more appropriate.</p>
<p><tt>satisfies?</tt> works also, however, so I have attached a new 'alt' patch.</p><p>The first patch is in fact faster when running the following code:</p>
<p> (time (-&gt;&gt; (repeat 1000 (vec (range 1000)))<br/>
vec<br/>
(r/mapcat identity)<br/>
(r/map inc)<br/>
(r/filter even?)<br/>
(r/fold +)))</p>
<p>This takes about 700 msecs. Using the first patch this terminates 100-300 msecs faster. This is after repeated (but informal) testing.</p>
<p>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.</p>
<p>(Note that the 2nd and 3rd patch also contain a fix for <tt>Cat</tt> and include more unit tests. The first patch should preferably not be applied as-is.)</p><p>Yeah you're timing too many things, including <tt>vec</tt>, <tt>range</tt>, lazy sequences. Also testing a small N. Take a look at the reducers example on the Mori README - <a href="https://github.com/swannodette/mori">https://github.com/swannodette/mori</a>. Thanks.</p><p>I tried running the following code:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(let [coll (vec (repeat 1000 (vec (range 10))))]
(time (doseq [n (range 1000)]
(-&gt;&gt; coll
(r/mapcat identity)
(r/map inc)
(r/filter even?)
(r/fold +)))))</pre>
</div></div>
<p>Some of the last results I got were:</p>
<p>1st patch: 75680 msecs<br/>
2nd patch: 76585 msecs</p>
<p>Truth be told, although the first patch seemed to win most of the times, sometimes the second patch was faster.</p>
<p>One other thing I tried was removing the <tt>implements?</tt>/<tt>satisfies?</tt> check from the second patch and overriding the protocol method coll-fold for the type <tt>object</tt> instead (as in the first patch). This 'hybrid' approach generally (but not always) seemed to result in a slowdown.</p>
<p>I'm not sure how I should proceed. Should I perhaps just run both patches simultaneously for several minutes?</p><p>This is still a bad way to do timing, you're recording the cost of range and seq'ing. Use <tt>dotimes</tt>.</p><p>Hm. I guess the lazy sequence does lead to a lot of allocations.</p>
<p>Alright, I rewrote my test and ran it a few more times. I now also tested on both vectors and arrays.</p>
<p>Patch 1 needed a slight tweak. When coll-fold is invoked, patch 1 only specifies a fallback for type <tt>object</tt> (i.e. <tt>r/reduce</tt> is called). I had to add the same fallback for type <tt>array</tt>. (This is weird!)</p>
<p>So here are the results.</p>
<p>For vectors:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(let [coll (vec (repeat 100 (vec (range 100))))]
(time (dotimes [n 3000]
(-&gt;&gt; coll
(r/mapcat identity)
(r/map inc)
(r/filter even?)
(r/fold +)))))</pre>
</div></div>
<p>Patch 1: 205872 msecs<br/>
Patch 2: 210756 msecs</p>
<p>For arrays:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(let [coll (into-array (repeat 100 (into-array (range 100))))]
(time (dotimes [n 3000]
(-&gt;&gt; coll
(r/mapcat identity)
(r/map inc)
(r/filter even?)
(r/fold +)))))</pre>
</div></div>
<p>Patch 1: 123567 msecs<br/>
Patch 2: 119704 msecs</p>
<p>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.</p>
<p>This makes sense.</p>
<p>In patch 1 <tt>reducer</tt> will call <tt>-reduce</tt> directly. In patch 2, <tt>reducer</tt> first calls <tt>r/reduce</tt>, which calls <tt>-reduce</tt> if the collection is a vector and <tt>array-reduce</tt> 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.</p>
<p>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?</p>
<p>&#8211;</p>
<p>I just realized that patch 2 is semantically slightly different from what Clojure does, although perhaps this is a bug in Clojure: &lt;<a href="https://groups.google.com/forum/#!searchin/clojure-dev/kv-reduce/clojure-dev/bEqECvbExGo/iW4B2vEUh8sJ">https://groups.google.com/forum/#!searchin/clojure-dev/kv-reduce/clojure-dev/bEqECvbExGo/iW4B2vEUh8sJ</a>&gt;. My suggestion to use a macro (or copy and paste) to avoid the extra function call in patch 2, could also fix this discrepancy.</p><p>How are you benchmarking this? With V8? JavaScriptCore? SpiderMonkey? In the browser? What optimization settings, etc.</p><p>I used repljs (Rhino?). I'll test again in a more realistic setting tomorrow.</p><p>Yeah, benchmarking with Rhino isn't informative.</p><p>I compiled the same code (with n=3000) using <tt>cljs</tt> with <tt>"{:optimizations :advanced}"</tt>.</p>
<p>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:</p>
<ul class="alternate" type="square">
<li>Open the browser</li>
<li>Open the developer console</li>
<li>Run the benchmark for patch 1</li>
<li>Run the benchmark for patch 2</li>
<li>Run the benchmark for patch 1 and write down the result</li>
<li>Run the benchmark for patch 2 and write down the result</li>
<li>Close the browser</li>
</ul>
<p>Firefox:</p>
<ul class="alternate" type="square">
<li>Patch 1. Vectors: 26057 msecs</li>
<li>Patch 1. Arrays: 25026 msecs</li>
<li>Patch 2. Vectors: 26258 msecs</li>
<li>Patch 2. Arrays: 36653 msecs</li>
<li>Summary: Patch 1 is faster for vectors and arrays</li>
</ul>
<p>Chrome:</p>
<ul class="alternate" type="square">
<li>Patch 1. Vectors: 7804 msecs</li>
<li>Patch 1. Arrays: 7092 msecs</li>
<li>Patch 2. Vectors: 7754 msecs</li>
<li>Patch 2. Arrays: 6768 msecs</li>
<li>Summary: Patch 2 is faster for vectors and arrays</li>
</ul>
<p>Safari:</p>
<ul class="alternate" type="square">
<li>Patch 1. Vectors: 167230 msecs</li>
<li>Patch 1. Arrays: 108780 msecs</li>
<li>Patch 2. Vectors: 173940 msecs</li>
<li>Patch 2. Arrays: 110012 msecs</li>
<li>Summary: Patch 1 is faster for vectors and arrays</li>
</ul>
<p>I'm not sure what to make of this. </p><p>I have attached a new version of the first patch.</p>
<p>This patch fixes an issue with <tt>r/Cat</tt>. (This issue was also addressed in the second and third patch. A unit test is included.).</p>
<p>This patch also fixes <tt>r/fold</tt> for arrays.</p>
<p>To summarize, a choice needs to be made between the following patches.</p>
<ul class="alternate" type="square">
<li><a href="http://dev.clojure.org/jira/browse/CLJS-736" title="Functions folder and reducer broken for types nil and array + fix for typo">CLJS-736</a>-patch-1-redux.patch</li>
<li><a href="http://dev.clojure.org/jira/browse/CLJS-736" title="Functions folder and reducer broken for types nil and array + fix for typo">CLJS-736</a>-alt.patch (uses implements?) / CLJS-alt-satisfies.patch (uses satisfies?)</li>
</ul>
<p>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.</p>
<p>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'. </p><p>The benchmarks would be more informative if they explained the performance before and after that patch.</p><p><tt>r/reduce</tt> previously didn't work for nil or JavaScript arrays.</p>
<p>One reason why I have trouble recommending a patch is that I don't know what use case you would like to optimize for.</p><p>Yes but now that we have new logic we can at least test the lack of regression on the <b>other</b> types.</p><p>Ok I tried to apply this patch and run <tt>./script/benchmarks</tt> 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 - <a href="http://github.com/clojure/clojurescript/wiki/Running-the-tests">http://github.com/clojure/clojurescript/wiki/Running-the-tests</a>. Then you can also run the benchmarks at the command line. I see there aren't any reducers benchmarks, I will add some.</p>Global RankPatchCode and Test[CLJS-900] Parameterize caching strategyhttp://dev.clojure.org/jira/browse/CLJS-900
ClojureScript<p>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.</p>CLJS-900Parameterize caching strategyTaskMinorOpenUnresolvedUnassignedDavid NolenWed, 3 Dec 2014 07:37:44 -0600Wed, 3 Dec 2014 07:42:34 -060000Global Rank[CLJS-797] Nested 'for' loops (3+ deep) in Android Chrome cause "Uncaught RangeError: Maximum call stack size exceeded"http://dev.clojure.org/jira/browse/CLJS-797
ClojureScript<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(<span class="code-keyword">do</span> (println <span class="code-quote">"<span class="code-keyword">for</span> loop test: 2 deep"</span>)
(<span class="code-keyword">for</span> [a [[1]]]
(<span class="code-keyword">for</span> [b a]
b)))
;; <span class="code-keyword">this</span> compiles and runs fine in the browser
(<span class="code-keyword">do</span> (println <span class="code-quote">"<span class="code-keyword">for</span> loop test: 3 deep"</span>)
(doall
(<span class="code-keyword">for</span> [a [[[1]]]]
(<span class="code-keyword">for</span> [b a]
(<span class="code-keyword">for</span> [c b]
c)))))
;; <span class="code-keyword">this</span> fails <span class="code-keyword">while</span> the page loads, with the error: Uncaught RangeError: Maximum call stack size exceeded</pre>
</div></div>
<p>The above works fine in a desktop browser. For some reason the error condition only happens on the Android Chrome browser.</p>
<p>Let me know if any further details are required.</p>Android 4.3, Chrome 34, ClojureScript 2202CLJS-797Nested 'for' loops (3+ deep) in Android Chrome cause "Uncaught RangeError: Maximum call stack size exceeded"DefectMinorOpenUnresolvedUnassignedJohn M. Newman IIIWed, 16 Apr 2014 00:45:52 -0500Thu, 17 Apr 2014 11:04:26 -050001Global Rank[CLJS-1067] Shared AOT cache for dependencies in JARshttp://dev.clojure.org/jira/browse/CLJS-1067
ClojureScript<p>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.</p>CLJS-1067Shared AOT cache for dependencies in JARsDefectMinorOpenUnresolvedUnassignedDavid NolenThu, 26 Feb 2015 16:32:37 -0600Fri, 27 Feb 2015 09:27:53 -060001Global Rank[CLJS-1123] this-as unexpectedly binds js/window when used within function with post-conditionhttp://dev.clojure.org/jira/browse/CLJS-1123
ClojureScript<p>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.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-none">(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</pre>
</div></div>CLJS-1123this-as unexpectedly binds js/window when used within function with post-conditionDefectMinorOpenUnresolvedUnassignedJ. S. ChoiSun, 15 Mar 2015 22:27:48 -0500Mon, 16 Mar 2015 06:21:00 -050001<p>This is almost certainly a different manifestation of <a href="http://dev.clojure.org/jira/browse/CLJS-719" title="this-as behaves incorrectly in &quot;scoping function&quot;">CLJS-719</a>.</p><p>Just looked at the generated javascript. As David mentioned the problem is the extra function generated to get the result for the :post condition.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">dummy.f_no_post_condition = (function f_no_post_condition(argument){
<span class="code-keyword">var</span> <span class="code-keyword">this</span>$ = <span class="code-keyword">this</span>;
<span class="code-keyword">var</span> G__82157 = argument;
<span class="code-keyword">var</span> G__82158 = <span class="code-keyword">this</span>$;
<span class="code-keyword">return</span> console.log(G__82157,G__82158);
});
dummy.f_with_post_condition = (function f_with_post_condition(argument){
<span class="code-keyword">var</span> _PERCENT_ = (function (){<span class="code-keyword">var</span> <span class="code-keyword">this</span>$ = <span class="code-keyword">this</span>;
<span class="code-keyword">var</span> G__82161 = argument;
<span class="code-keyword">var</span> G__82162 = <span class="code-keyword">this</span>$;
<span class="code-keyword">return</span> console.log(G__82161,G__82162);
})();
<span class="code-keyword">return</span> _PERCENT_;
});
dummy.test_object = {<span class="code-quote">"methodWithPostcondition"</span>: dummy.f_with_post_condition, <span class="code-quote">"methodNoPostcondition"</span>: dummy.f_no_post_condition};
dummy.f_with_post_condition(<span class="code-quote">"A"</span>);
dummy.test_object.methodNoPostcondition(<span class="code-quote">"B"</span>);
dummy.test_object.methodWithPostcondition(<span class="code-quote">"C"</span>);</pre>
</div></div>Global Rank[CLJS-1151] Noisy errors when referring to symbol in undefined nshttp://dev.clojure.org/jira/browse/CLJS-1151
ClojureScript<p>Run through the Quick Start to the point where you have the browser REPL running.</p>
<p>If you refer to a symbol in an undefined ns you will get really noisy errors:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; foo.bar/a
WARNING: Use of undeclared Var foo.bar/a at line 1 &lt;cljs repl&gt;
ReferenceError: foo is not defined
ReferenceError: foo is not defined
at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:1:89)
</span> at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:9:3)
</span> at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:14:4)
</span> at http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:267
</span> at clojure$browser$repl$evaluate_javascript (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:45:4)
</span> at <span class="code-object">Object</span>.callback (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:242:169)
</span> at goog.messaging.AbstractChannel.deliver (http:<span class="code-comment">//localhost:9000/out/goog/messaging/abstractchannel.js:142:13)
</span> at goog.net.xpc.CrossPageChannel.xpcDeliver (http:<span class="code-comment">//localhost:9000/out/goog/net/xpc/crosspagechannel.js:733:12)
</span> at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http:<span class="code-comment">//localhost:9000/out/goog/net/xpc/nativemessagingtransport.js:321:13)
</span> at <span class="code-object">Object</span>.goog.events.fireListener (http:<span class="code-comment">//localhost:9000/out/goog/events/events.js:741:21)</span></pre>
</div></div>
<p>Now, define the namespace, but don't actually define the symbol. For example:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns foo.bar)
(def z 3)</pre>
</div></div>
<p>Now, require the namespace and do the same. The noise will go away.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (require 'foo.bar)
nil
ClojureScript:cljs.user&gt; foo.bar/a
WARNING: Use of undeclared Var foo.bar/a at line 1 &lt;cljs repl&gt;
nil</pre>
</div></div>
<p>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 <tt>foo</tt>:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; foo.baz/a
WARNING: No such namespace: foo.baz, could not locate foo/baz.cljs at line 1 &lt;cljs repl&gt;
WARNING: Use of undeclared Var foo.baz/a at line 1 &lt;cljs repl&gt;
TypeError: Cannot read property 'a' of undefined
TypeError: Cannot read property 'a' of undefined
at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:1:96)
</span> at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:9:3)
</span> at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:14:4)
</span> at http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:267
</span> at clojure$browser$repl$evaluate_javascript (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:45:4)
</span> at <span class="code-object">Object</span>.callback (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:242:169)
</span> at goog.messaging.AbstractChannel.deliver (http:<span class="code-comment">//localhost:9000/out/goog/messaging/abstractchannel.js:142:13)
</span> at goog.net.xpc.CrossPageChannel.xpcDeliver (http:<span class="code-comment">//localhost:9000/out/goog/net/xpc/crosspagechannel.js:733:12)
</span> at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http:<span class="code-comment">//localhost:9000/out/goog/net/xpc/nativemessagingtransport.js:321:13)
</span> at <span class="code-object">Object</span>.goog.events.fireListener (http:<span class="code-comment">//localhost:9000/out/goog/events/events.js:741:21)
</span>ClojureScript:cljs.user&gt; goo.baz/a
WARNING: No such namespace: goo.baz, could not locate goo/baz.cljs at line 1 &lt;cljs repl&gt;
WARNING: Use of undeclared Var goo.baz/a at line 1 &lt;cljs repl&gt;
ReferenceError: goo is not defined
ReferenceError: goo is not defined
at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:1:89)
</span> at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:9:3)
</span> at eval (eval at &lt;anonymous&gt; (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:272), &lt;anonymous&gt;:14:4)
</span> at http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:42:267
</span> at clojure$browser$repl$evaluate_javascript (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:45:4)
</span> at <span class="code-object">Object</span>.callback (http:<span class="code-comment">//localhost:9000/out/clojure/browser/repl.js:242:169)
</span> at goog.messaging.AbstractChannel.deliver (http:<span class="code-comment">//localhost:9000/out/goog/messaging/abstractchannel.js:142:13)
</span> at goog.net.xpc.CrossPageChannel.xpcDeliver (http:<span class="code-comment">//localhost:9000/out/goog/net/xpc/crosspagechannel.js:733:12)
</span> at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http:<span class="code-comment">//localhost:9000/out/goog/net/xpc/nativemessagingtransport.js:321:13)
</span> at <span class="code-object">Object</span>.goog.events.fireListener (http:<span class="code-comment">//localhost:9000/out/goog/events/events.js:741:21)</span></pre>
</div></div>Quick Start / OS X / ChromeCLJS-1151Noisy errors when referring to symbol in undefined nsDefectMinorOpenUnresolvedUnassignedMike FikesThu, 19 Mar 2015 15:40:43 -0500Sun, 22 Mar 2015 09:52:33 -05000.0-312600<p>Clarification on the description: When defining the <tt>foo.bar</tt> ns, I actually created a source file <tt>src/foo/bar.cljs</tt> containing the ns declaration and the <tt>def z</tt>.</p><p>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.</p>Global Rank[CLJS-1211] Automatically requiring :main namespace under :none fails in IE9http://dev.clojure.org/jira/browse/CLJS-1211
ClojureScript<p>Automatic goog/base.js inclusion using :none &amp; :main doesn't work in Internet Explorer 9. The following error message is printed to the console:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>ClojureScript could not load :main, did you forget to specify :asset-path?
</pre>
</div></div>
<p>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.</p>
<p>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:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>SCRIPT5022: Undefined nameToPath for goog.string
base.js, line 753 character 9
</pre>
</div></div>
<p>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.</p>
Internet Explorer 9CLJS-1211Automatically requiring :main namespace under :none fails in IE9DefectMinorOpenUnresolvedUnassignedImmo HeikkinenFri, 17 Apr 2015 06:16:50 -0500Fri, 17 Apr 2015 06:16:50 -05000.0-30580.0-31150.0-31960.0-31170.0-31190.0-31230.0-312600Global Rank[CLJS-890] Incorrect behaviour of (str obj) when obj has valueOf methodhttp://dev.clojure.org/jira/browse/CLJS-890
ClojureScript<p>Example</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(str #js {<span class="code-quote">"toString"</span> (fn [] <span class="code-quote">"hello"</span>) <span class="code-quote">"valueOf"</span> (fn [] 42)}) ; =&gt; <span class="code-quote">"42"</span></pre>
</div></div>
<p>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.</p>
<p>Example in js:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript"><span class="code-keyword">var</span> obj = {
toString: <span class="code-keyword">function</span>() { <span class="code-keyword">return</span> 'hello'; },
valueOf: <span class="code-keyword">function</span>() { <span class="code-keyword">return</span> 42; }
};
console.log(<span class="code-object">String</span>(obj)); =&gt; 'hello'
console.log(obj.toString()); =&gt; 'hello'
console.log('' + obj); =&gt; '42'</pre>
</div></div>
<p>Potential solution might be to use String() function. Using toString() won't work as described in this issue: <a href="http://dev.clojure.org/jira/browse/CLJS-847">http://dev.clojure.org/jira/browse/CLJS-847</a></p>CLJS-890Incorrect behaviour of (str obj) when obj has valueOf methodDefectMinorReopenedUnresolvedUnassignedNikita BeloglazovMon, 24 Nov 2014 09:52:14 -0600Sat, 25 Apr 2015 23:08:42 -050014<p>Is there a valid use case where toString and valueOf are not in sync? E.g. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(not= (.toString x) (js/<span class="code-object">String</span> (.valueOf x))</pre>
</div></div>
<p>If not, is it "incorrect" for the two methods to be out of sync?</p><p>Here is an example of such use case: <a href="https://github.com/processing-js/processing-js/blob/master/src/Objects/Char.js">https://github.com/processing-js/processing-js/blob/master/src/Objects/Char.js</a> <br/>
That's how I found this bug.</p><p>Thanks for the link. I see what you mean.</p><p>The problem with going with <tt>String</tt> appears to be a massive performance hit to printing <a href="http://jsperf.com/string-vs-tostring2/6">http://jsperf.com/string-vs-tostring2/6</a>.</p>
<p>Unless a brilliant idea is proposed this seems best solved / worked around in user code.</p><p>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. <br/>
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. </p><p>Sorry going back over this I believe the issue is really that we simply need to backout <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a>.</p><p>reverted <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> in master</p><p><a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> only deals with the str <b>macro</b>. Aren't we still going to have str <b>function</b> problem because of <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>? <a href="https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642">https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642</a> (also Yet if we use toString there, Safari 6.0.5 blows up. Maybe we need {{<span class="error">&#91;o&#93;</span>.join('')}}? Depending on where the bug is this may be wrong in Safari 6.0.5 too.</p>
<p>What we need to do very specifically is somehow get the return value of the (in ECMASCRIPT-ese) <tt>ToString</tt> abstract operation on the object (or the underlying <tt>ToPrimitive</tt> abstract operation with the String hint). String concat with the add operator </p>
<p>Options as I see it are:</p>
<ul>
<li><tt>x.toString()</tt> : Bad because of <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a></li>
<li>{{<span class="error">&#91;x&#93;</span>.join('')}} : Should work (and does right thing for null/undefined), but I think we should test in Safari 6.0.5. Also very slow.</li>
<li><tt>String<img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/error.gif" height="16" width="16" align="absmiddle" alt="" border="0"/></tt></li>
<li><tt>String.prototype.concat<img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/error.gif" height="16" width="16" align="absmiddle" alt="" border="0"/></tt></li>
<li><tt>String.prototype.slice(x,0)</tt> <tt>String.prototype.substring(x,0)</tt> <tt>String.prototype.substr(x, 0)</tt></li>
<li><tt>x.toString()</tt> normally, but <tt>String<img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/error.gif" height="16" width="16" align="absmiddle" alt="" border="0"/></tt> if we detect that we'll trigger <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>. (Can specialize on startup.)</li>
</ul>
<p>Is there any evidence that higher usage of str is actually problematic?</p><p>String concat using the addition operator uses an un-hinted <tt>ToPrimitive</tt> abstract call (which will try <tt>x.valueOf()</tt> first then <tt>x.toString()</tt>, usually) and then {{ToString}}s the result of <b>that</b>, so it's not an option unless we are concating primitive values.</p>
<p>Details:</p>
<ul>
<li>ToString <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-9.8">http://www.ecma-international.org/ecma-262/5.1/#sec-9.8</a></li>
<li>ToPrimitive <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-9.1">http://www.ecma-international.org/ecma-262/5.1/#sec-9.1</a></li>
<li>DefaultValue (called by ToPrimitive for Objects) <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8">http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8</a></li>
</ul>
<p>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.</p><blockquote><p>Is there any evidence that higher usage of str is actually problematic?</p></blockquote>
<p>Kevin Neaton, who opened <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>, 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 <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> applied) or it used {{<span class="error">&#91;x&#93;</span>.join('')}} (which hasn't been tested with Safari 6.0.5 yet, but probably works).</p>
<p>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 <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a> is applied.</p>
<p>I haven't pulled down master yet, but here is a test case which I bet will fail with the <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a> patch:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def tricky-obj #js {<span class="code-quote">"toString"</span> (fn [] <span class="code-quote">"hello"</span>) <span class="code-quote">"valueOf"</span> (fn [] 42)})
(<span class="code-keyword">assert</span> (= (apply str tricky-obj) <span class="code-quote">"hello"</span>)) ;; will get <span class="code-quote">"42"</span></pre>
</div></div><blockquote><p>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.</p></blockquote>
<p>To be clear, there are two issues here:</p>
<p><a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>: x.toString() fails on Safari 6.0.5. Workaround is ''+x (only done in str macro case).<br/>
<a href="http://dev.clojure.org/jira/browse/CLJS-890" title="Incorrect behaviour of (str obj) when obj has valueOf method">CLJS-890</a>: ''+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 <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>.</p>
<p>To make matters worse, it looks like the toString() error on Safari may only be triggered at certain JIT levels!</p><blockquote><p>Workaround is ''+x (only done in str macro case).</p></blockquote>
<p>I mean "Workaround is ''+x (only done in str <b>function</b> case)."</p><p>Can this bug be reopened meanwhile? If I understand correctly the fix should affect <a href="https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642">https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642</a> but this code still present in HEAD.</p><p>We've switched to <tt>goog.string.buildString</tt> in master <a href="https://github.com/clojure/clojurescript/commit/94eb8a960fef6aaca4ba44b251cefbfa04d0f6ac">https://github.com/clojure/clojurescript/commit/94eb8a960fef6aaca4ba44b251cefbfa04d0f6ac</a></p><p>Yes, that works. Cool, thanks!</p><p>Sorry for re-opening.</p>
<p>I was doing some profiling of my code and noticed a warning in the profiling output about cljs.core/str.</p>
<p>Chromes complains with: "Not optimized. Bad value context for arguments value", looking further at the implementation of goog.string.buildString</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">goog.string.buildString = function(var_args) {
<span class="code-keyword">return</span> Array.prototype.join.call(arguments, '');
};</pre>
</div></div>
<p>Given that we don't ever call it with more than one argument it is probably not best implementation choice.</p>
<p>Maybe skip the call and inline it ala</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(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] (<span class="code-keyword">if</span> (nil? x)
""
(.join #js [x] "")))
([x &amp; ys]
(loop [sb (<span class="code-object">StringBuffer</span>. (str x)) more ys]
(<span class="code-keyword">if</span> more
(recur (. sb (append (str (first more)))) (next more))
(.toString sb)))))</pre>
</div></div>
<p>I didn't follow this issue but why are we not using .toString? The buildString/array approach seems kind of hackish?</p>
<p>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.</p><p>Before:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;;; str
[], (str <span class="code-quote">"1"</span>), 1000000 runs, 254 msecs
[], (str 1), 1000000 runs, 266 msecs
[], (str nil), 1000000 runs, 80 msecs
[], (str <span class="code-quote">"1"</span> <span class="code-quote">"2"</span> <span class="code-quote">"3"</span>), 1000000 runs, 753 msecs</pre>
</div></div>
<p>After:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;;; str
[], (str <span class="code-quote">"1"</span>), 1000000 runs, 82 msecs
[], (str 1), 1000000 runs, 86 msecs
[], (str nil), 1000000 runs, 79 msecs
[], (str <span class="code-quote">"1"</span> <span class="code-quote">"2"</span> <span class="code-quote">"3"</span>), 1000000 runs, 242 msecs</pre>
</div></div>
<p>But I only tested V8, probably needs some verification.</p><div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(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] ""))
...)</pre>
</div></div>
<p>Does perform even better.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;;; str
[], (str <span class="code-quote">"1"</span>), 1000000 runs, 40 msecs
[], (str 1), 1000000 runs, 43 msecs
[], (str nil), 1000000 runs, 96 msecs
[], (str <span class="code-quote">"1"</span> <span class="code-quote">"2"</span> <span class="code-quote">"3"</span>), 1000000 runs, 117 msecs</pre>
</div></div>
<p>How many args should it inline?</p><p>I'd be OK with up to 4 then variadic.</p><p>There is some weird interaction between the code generated by the cljs.core/str macro and function.</p>
<p>The macro generates</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(str <span class="code-quote">"hello"</span> 1 <span class="code-quote">"world"</span> :yo nil)
yields
[cljs.core.str(<span class="code-quote">"hello"</span>),cljs.core.str((1)),cljs.core.str(<span class="code-quote">"world"</span>),cljs.core.str(<span class="code-keyword">new</span> cljs.core.Keyword(<span class="code-keyword">null</span>,<span class="code-quote">"yo"</span>,<span class="code-quote">"yo"</span>,1207083126)),cljs.core.str(<span class="code-keyword">null</span>)].join('');</pre>
</div></div>
<p>Given that str with 1 arg will basically unroll to</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[[<span class="code-quote">"hello"</span>].join(""), ...]</pre>
</div></div>
<p>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).</p><blockquote><p>Chromes complains with: "Not optimized. Bad value context for arguments value", looking further at the implementation of goog.string.buildString</p></blockquote>
<p>Chrome complains about the variadic function dispatch code in the same way, see <a href="http://dev.clojure.org/jira/browse/CLJS-916" title="Optimize use of js-arguments in array and variadic functions"><del>CLJS-916</del></a> plus patch.</p>
<blockquote><p>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).</p></blockquote>
<p>The Closure compiler is not smart enough to remove the intermediate array, which is why I filed <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> (which this ticket rolled back). I don't think JITs can do it either.</p>
<p>I am beginning to wonder if we should ignore the Safari 6.0.5 problem in <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a> that started all this string mess. To recap:</p>
<ol>
<li><a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> is accepted, which removes <tt>[123, x].join('')</tt> in the str macro case in favor of <tt>''&#43;123&#43;(cljs.core/str$arity$1 x)</tt> 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.</li>
<li><a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a> 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 <tt>''+x</tt>.</li>
<li>However, this breaks for objects that define valueOf (issue in current ticket), because in js <tt>''+x</tt> is the same as <tt>''+x.valueOf().toString()</tt> not <tt>''+x.toString()</tt>.</li>
<li>David considers using <tt>String()</tt> and variations but rejects because of performance hit.</li>
<li>David rolls back <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> from the string-concat back to the array-join style to fix.</li>
<li>Nikita and I point out that rolling back <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> only fixes the str <b>macro</b>, not the string <b>function</b>, which still uses <tt>js-str</tt> and hence string-concat.</li>
<li>David fixes the str <b>function</b> to use goog.string.buildString, which has the behavior of array.join. Behavior is now correct even on Safari 6.0.5.</li>
<li>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 <tt>[].join()</tt> directly.</li>
</ol>
<p>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.</p>
<p>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.</p>
<p>I think the options are:</p>
<ol>
<li>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.</li>
<li>Use <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> and toString (status quo before <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>), and ignore this problem for Safari 6.0.x.</li>
<li>Use <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a>, but add a <tt>number?</tt> check (with comment) to <tt>cljs.core/str$arity$1</tt> 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.</li>
</ol>
<p>Of course we should benchmark these approaches but my hunch is that 2 is faster than 3 is faster than 1.</p><p>We are not going to ignore Safari 6.0.X. Any decisions made about this ticket will include supporting it.</p><p>Update on some research I am doing into this.</p>
<p>I created a <a href="http://jsperf.com/cljs-core-str-possibilities">jsperf of alternative str implementations</a> that I am trying out. Right now I've only looked at one-arg str. I discovered a few things:</p>
<ul>
<li>{{''+<span class="error">&#91;x&#93;</span>}} is a faster alternative to <tt>[x].join('')</tt>.</li>
<li>Advanced compilation can compute {{''+<span class="error">&#91;x&#93;</span>}} at compile time if <tt>x</tt> 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.</li>
<li>However, using an intermediate array (even if a preallocated singleton) is still slower than the old <tt>&#40;if (nil? x) "" (.toString x))</tt></li>
<li>Using a switch statement is as least as fast as the str-tostr baseline, usually faster.</li>
<li>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 <a href="http://www.browserstack.com">Browserstack</a> has this version of Safari.</li>
</ul>
<p>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 <tt>''+x</tt> now instead of an array-join.)</p><p>Sorry, got side-tracked for a bit.</p>
<p>@Francis: Thanks for the recap.</p>
<p>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.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-quote">"".concat(obj); <span class="code-comment">// "</span>42"
</span><span class="code-quote">"".concat(obj, "</span><span class="code-quote">"); <span class="code-comment">// "</span>hello"
</span><span class="code-object">String</span>.prototype.concat(obj, <span class="code-quote">"") <span class="code-comment">// "</span>hello"
</span><span class="code-object">String</span>.prototype.concat(<span class="code-quote">"", obj) <span class="code-comment">// "</span>hello"</span></pre>
</div></div>
<p>But no idea if String.concat works, also it behaves odd with regards to valueOf.</p>
<p><a href="http://jsperf.com/js-string-concat-variants">http://jsperf.com/js-string-concat-variants</a></p>
<p>Perf is also inconclusive since Firefox appears to be cheating.</p>
<p>Tested that jsperf with Safari 6.0.5 using Browserstack, results are there.</p>
<p>Note I could <b>not</b> reproduce <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a> because str-tostr does <b>not</b> fail as expected. I will try harder now that I have a browser to test.</p><p>Still cannot reproduce <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>.</p>
<p><a href="https://dl.dropboxusercontent.com/u/18386249/code/strtest.html">This script</a> 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.</p>
<p>In <a href="https://github.com/wycats/handlebars.js/pull/440">this thread</a> I found <a href="https://dl.dropboxusercontent.com/u/18386249/code/handlebar_str_typeerror.html">this "minimal" script</a> 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.</p>
<p>Hypotheses:</p>
<ol>
<li>This error does not affect 6.0.5 but maybe 6.0.4 or lower.</li>
<li>BrowserStack's system somehow mitigates the bug, meaning we need a "real" Lion Safari 6.0.x to test.</li>
<li>These tests only fail under the correct phase of the moon.</li>
</ol>
<p>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. <a href="http://dev.clojure.org/jira/browse/CLJS-801" title="str macro emits unoptimizable js code"><del>CLJS-801</del></a> should also be safe to reapply because the root cause of all issues is the implementation 1-arity of the cljs.core/str function.</p>
<p>I have also asked for Kevin's help back in <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>. (Kevin was the original reporter of the Safari 6.0.x issue.)</p><p>Made a <a href="http://jsperf.com/cljs-core-str-variadic-possibilities">jsperf of variadic cases</a>. 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.</p>
<p>Also updated <a href="http://jsperf.com/cljs-core-str-possibilities/2">arity-one cases</a> with a str using switch and never using toString. Nearly 50% slower than using switch or toString on Chrome, smaller on Safari.</p>
<p>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.</p>
<p>I suggest something like this as a new str (which doesn't use reduce, but could):</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn str
([x]
(<span class="code-keyword">case</span> (js* <span class="code-quote">"typeof ~{}"</span> x)
<span class="code-quote">"string"</span> x
<span class="code-quote">"object"</span> (<span class="code-keyword">if</span> (identical? nil x) "" (.toString x))
(<span class="code-quote">"<span class="code-object">boolean</span>"</span> <span class="code-quote">"number"</span>) (js-str x)
<span class="code-quote">"undefined"</span> ""
(js-str #js [x]))) ;; insurance against Safari 6.0.x TypeError bug.
([a b] (js* <span class="code-quote">"~{}+~{}"</span> (str a) (str b)))
([a b c] (js* <span class="code-quote">"~{}+~{}+~{}"</span> (str a) (str b) (str c)))
([a b c d] (js* <span class="code-quote">"~{}+~{}+~{}+~{}"</span> (str a) (str b) (str c) (str d)))
([a b c d &amp; more]
(loop [s (str a b c d) [e f g h &amp; r] more]
(let [s' (js* <span class="code-quote">"~{}+~{}+~{}+~{}+~{}"</span> s e f g h)]
(<span class="code-keyword">if</span> (nil? r)
s'
(recur s' r))))))</pre>
</div></div><p>First cut of a possible patch that resolves this while not breaking <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>. Should wait for confirmation that this does not break Safari 6.0.x.</p><p>Oops forgot tests.</p><p>Update in <a href="http://dev.clojure.org/jira/browse/CLJS-847" title="TypeError in cljs.core/str using Safari 6.0.5"><del>CLJS-847</del></a>: 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.</p>
<p>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 <tt>(if (nil? x) "" (.toString x))</tt> implementation. However, you could also try the patch on this ticket (using a typeof switch), which at least (<em>handwaving</em>) <b>might</b> 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.)</p><p>I wonder if you considered swapping str function at runtime during CLJS init phase. </p>
<p>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.</p>
<p>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.</p>
Global Rank[CLJS-1091] Compose JavaScript dependency indexeshttp://dev.clojure.org/jira/browse/CLJS-1091
ClojureScript<p>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.</p>CLJS-1091Compose JavaScript dependency indexesDefectMinorOpenUnresolvedUnassignedDavid NolenSat, 7 Mar 2015 11:29:24 -0600Wed, 29 Apr 2015 07:21:41 -050000Global Rank[CLJS-1245] Implement bound-fnhttp://dev.clojure.org/jira/browse/CLJS-1245
ClojureScript<p>See discussion on <a href="http://dev.clojure.org/jira/browse/CLJS-210">http://dev.clojure.org/jira/browse/CLJS-210</a></p>CLJS-1245Implement bound-fnEnhancementMinorOpenUnresolvedUnassignedBrandon BloomSun, 3 May 2015 17:11:01 -0500Tue, 5 May 2015 07:50:11 -050000Global Rank[CLJS-1266] Node: Rename .cljs to .cljc -> old filenames in stacktracehttp://dev.clojure.org/jira/browse/CLJS-1266
ClojureScript<p>Using QuickStart, set up Node REPL.</p>
<p>Manually add a <tt>foo/bar.cljs</tt> to filesystem with </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns foo.bar)
(defn <span class="code-keyword">throw</span>-ex [] (ffirst 1))
(defn call-me [] (<span class="code-keyword">throw</span>-ex))</pre>
</div></div>
<p>Check that it works:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">cljs.user=&gt; (require 'foo.bar)
nil
cljs.user=&gt; (foo.bar/call-me)
repl:13
<span class="code-keyword">throw</span> e__4210__auto__;
^
Error: 1 is not ISeqable
at <span class="code-object">Object</span>.cljs$core$seq [as seq] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:956:20)
at <span class="code-object">Object</span>.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 <span class="code-object">Object</span>.exports.runInThisContext (vm.js:74:17)
at Domain.&lt;anonymous&gt; ([stdin]:41:34)</pre>
</div></div>
<p>Then manually move <tt>bar.cljs</tt> to <tt>bar.cljc</tt> and add a new symbol so it looks like:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns foo.bar)
(defn <span class="code-keyword">throw</span>-ex [] (ffirst 1))
(defn call-me [] (<span class="code-keyword">throw</span>-ex))
(defn call-again [] (call-me))</pre>
</div></div>
<p>Then reload the ns and use the new symbol:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">cljs.user=&gt; (require 'foo.bar :reload)
nil
cljs.user=&gt; (foo.bar/call-again)
repl:13
<span class="code-keyword">throw</span> e__4210__auto__;
^
Error: 1 is not ISeqable
at <span class="code-object">Object</span>.cljs$core$seq [as seq] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:956:20)
at <span class="code-object">Object</span>.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 <span class="code-object">Object</span>.exports.runInThisContext (vm.js:74:17)</pre>
</div></div>
<p>This illustrates the defect. <tt>call_again</tt> and the other symbols are shown as being in the old filename.</p>
<p>Stop the REPL and restart it to see correct behavior:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">cljs.user=&gt; :cljs/quit
orion:hello_world-node mfikes$ rlwrap java -cp cljs.jar:src clojure.main node_repl.clj
Reading analysis cache <span class="code-keyword">for</span> 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=&gt; (require 'foo.bar)
nil
cljs.user=&gt; (foo.bar/call-again)
repl:13
<span class="code-keyword">throw</span> e__4210__auto__;
^
Error: 1 is not ISeqable
at <span class="code-object">Object</span>.cljs$core$seq [as seq] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:956:20)
at <span class="code-object">Object</span>.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 <span class="code-object">Object</span>.exports.runInThisContext (vm.js:74:17)</pre>
</div></div>CLJS-1266Node: Rename .cljs to .cljc -> old filenames in stacktraceDefectMinorOpenUnresolvedUnassignedMike FikesTue, 12 May 2015 12:47:58 -0500Tue, 12 May 2015 14:04:59 -05000.0-326901<p>FWIW as a comparison, the same use case works properly with Clojure 1.7.0-beta2.</p>Global Rank[CLJS-1320] clojure.string/split adds separator matches & failed matches (nil) when the separator is a regex with alternationhttp://dev.clojure.org/jira/browse/CLJS-1320
ClojureScript<p>I want to split a string on "; ", and optionally discard a final ";". So, I tried:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(clojure.string/split <span class="code-quote">"ab; ab;"</span> #<span class="code-quote">"(; )|(;$)"</span>)</pre>
</div></div>
<p>In Clojure, this does what I want:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[<span class="code-quote">"ab"</span> <span class="code-quote">"ab"</span>]</pre>
</div></div>
<p>In ClojureScript, I get:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[<span class="code-quote">"ab"</span> <span class="code-quote">"; "</span> nil <span class="code-quote">"ab"</span> nil <span class="code-quote">";"</span>]</pre>
</div></div>
<p>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?</p>CLJS-1320clojure.string/split adds separator matches & failed matches (nil) when the separator is a regex with alternationDefectMinorOpenUnresolvedUnassignedlvhFri, 26 Jun 2015 17:58:28 -0500Sat, 27 Jun 2015 02:44:30 -05000.0-330800Global Rank[CLJS-1259] Incorrect warnings on type hinted mathshttp://dev.clojure.org/jira/browse/CLJS-1259
ClojureScript<p>Variables type hinted as int or double are not recognized as numbers, e.g.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def ^<span class="code-object">int</span> i 1)
(+ i i)
WARNING: cljs.core/+, all arguments must be numbers, got [<span class="code-object">int</span> <span class="code-object">int</span>] instead. at line 1 &lt;cljs repl&gt;
2</pre>
</div></div>CLJS-1259Incorrect warnings on type hinted mathsDefectMinorOpenUnresolvedUnassignedErik OuchterlonybugmathtypehintsSat, 9 May 2015 03:18:50 -0500Tue, 14 Jul 2015 06:07:03 -05000.0-325501<p>The real issue is that there is no support for numeric type hints.</p>Global Rank[CLJS-1255] cljs.test file-and-line detection is not useful in browser testinghttp://dev.clojure.org/jira/browse/CLJS-1255
ClojureScript<p>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:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">"Error
at http:<span class="code-comment">//localhost:3449/js/cljs/test.js:261:69
</span> at cljs$test$do_report (http:<span class="code-comment">//localhost:3449/js/cljs/test.js:268:3)
</span> at http:<span class="code-comment">//localhost:3449/js/test/test_tests.js:491:21
</span> at test.test_tests.test_has_fails.cljs$lang$test (http:<span class="code-comment">//localhost:3449/js/test/test_tests.js:502:4)
</span> at http:<span class="code-comment">//localhost:3449/js/cljs/test.js:384:42
</span> at http:<span class="code-comment">//localhost:3449/js/cljs/test.js:387:4
</span> at cljs$test$run_block (http:<span class="code-comment">//localhost:3449/js/cljs/test.js:320:13)
</span> ..."</pre>
</div></div>
<p>The `file-and-line` stack trace parser doesn't parse this correctly, resulting in a message like this:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">FAIL in (test-function) (at http:384:42)</pre>
</div></div>
<p>Note the lack of a useful file/namespace reference, and that the line number refers to the compiled javascript rather than the source clojurescript.</p>ChromeCLJS-1255cljs.test file-and-line detection is not useful in browser testingDefectMinorOpenUnresolvedUnassignedStephen NelsonThu, 7 May 2015 21:07:49 -0500Tue, 14 Jul 2015 06:09:23 -05000.0-321101<p>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 <tt>&amp;form</tt> to the <tt>do-report</tt> calls generated by <tt>assert-expr</tt>. This approach was great for internal use but might not be suitable for cljs.test as it could reduce portability of <tt>assert-expr</tt> between clojure and clojurescript. Another approach could be dynamically bind source metadata in the body generated by <tt>try-expr</tt>. I'd be willing to implement and contribute code if you can provide some indication of your preferred approach.</p>
<p>Our version of <tt>assert-expr</tt> also injected a 'reporter function', {{(function(a,b,c){a.apply(b.c)})}}, which we would invoke from report, e.g. <tt>(reporter (.-debug js/console) js/console args)</tt>. 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.</p><p>The correct thing to do here is to move the browser REPL stacktrace parsing into a shared library i.e. <tt>.cljc</tt> that can be loaded into either environment to handle browser difference.</p>Global Rank[CLJS-1390] clojure.walk treats vectors diffently from Clojure versionhttp://dev.clojure.org/jira/browse/CLJS-1390
ClojureScript<p>The latest patch to clojure.walk (<a href="https://github.com/clojure/clojurescript/commit/f706fabfd5f952c4dfb4dc2caeea92f9e00d8287">https://github.com/clojure/clojurescript/commit/f706fabfd5f952c4dfb4dc2caeea92f9e00d8287</a>) ports the line of the Clojure version </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(instance? clojure.lang.IMapEntry form) (<span class="code-keyword">outer</span> (vec (map <span class="code-keyword">inner</span> form)))</pre>
</div></div>
<p>with the line</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(satisfies? IMapEntry form) (<span class="code-keyword">outer</span> (vec (map <span class="code-keyword">inner</span> form)))</pre>
</div></div>
<p>ClojureScript implements IMapEntry on any vector which I assume is intended.</p>
<p>In Clojure, for vectors this case falls:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(coll? form) (<span class="code-keyword">outer</span> (into (empty form) (map <span class="code-keyword">inner</span> form)))</pre>
</div></div>
<p>This makes a difference because empty preserves metadata.<br/>
I. e.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(meta (prewalk (fn [form]
(vary-meta form assoc :foo <span class="code-keyword">true</span>))
[]))</pre>
</div></div>
<p>gives {:foo true} on earlier ClojureScript versions and Clojure, but nil on the latest version.</p>
<p>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.</p>CLJS-1390clojure.walk treats vectors diffently from Clojure versionDefectMinorOpenUnresolvedUnassignedLeon GrapenthinMon, 3 Aug 2015 16:10:57 -0500Mon, 3 Aug 2015 16:12:18 -05001.7.2801Global Rank[CLJS-1421] Enable Asynchronous cljs.js/*eval-fn*http://dev.clojure.org/jira/browse/CLJS-1421
ClojureScript<p>In bootstrapped ClojureScript cljs.js/<b>eval-fn</b> 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?</p>CLJS-1421Enable Asynchronous cljs.js/*eval-fn*EnhancementMinorOpenUnresolvedUnassignedMatthew MolloyasynchronousbootstrapFri, 14 Aug 2015 10:18:33 -0500Sun, 16 Aug 2015 00:16:33 -05001.7.4800<p>This ticket needs more rationale. Can you elaborate on the usecase?</p><p>My usecase is an asynchronous eval function</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(fn *eval-fn*
[{:keys [source]}]
(js/chrome.devtools.inspectedWindow.eval source
(fn [result err]
(<span class="code-keyword">if</span> result
(callback result)
(callback err))))</pre>
</div></div>
<p>There must be other people who have situations like this.</p><p>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, <tt>:async-eval</tt>.</p>Global Rank[CLJS-1428] Add a cljs.core/*command-line-args* varhttp://dev.clojure.org/jira/browse/CLJS-1428
ClojureScript<p>Add a <tt>cljs.core/&#42;command-line-args*</tt> var that mimics Clojure's:</p>
<p><a href="https://github.com/clojure/clojure/blob/4bb1dbd596f032621c00a670b1609a94acfcfcab/src/clj/clojure/core.clj#L6148">https://github.com/clojure/clojure/blob/4bb1dbd596f032621c00a670b1609a94acfcfcab/src/clj/clojure/core.clj#L6148</a></p>
<p>Rationale:<br/>
1) Simplifies writing command-line scripts in ClojureScript if this var is universally available.<br/>
2) Consistency with Clojure.</p>
<p>Existing tooling can ignore the var (it would be initialized with <tt>nil</tt>).</p>
<p>Command-line REPLs or other command-line environments can bind a sequence to this var when launched.</p>CLJS-1428Add a cljs.core/*command-line-args* varEnhancementMinorOpenUnresolvedUnassignedMike FikesSun, 16 Aug 2015 09:20:56 -0500Tue, 1 Sep 2015 16:27:43 -05001.7.4811<p>In this file: <a href="https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/nodejs.cljs">https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/nodejs.cljs</a> Looks like you could set this: (def &#42;command-line-args&#42; (.-argv process)) and it'd be accessible under nodejs/&#42;command-line-args&#42;. 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. </p>
<p>Maybe get the target var somehow and set it based on that--similar to how the nodejs file is loaded?</p>
<p>Found this: src/main/clojure/cljs/core.cljc and saw references to a ns called env.</p>
<p>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.</p><p>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. </p>Global Rank[CLJS-1407] Exposing output file dependency graph in APIhttp://dev.clojure.org/jira/browse/CLJS-1407
ClojureScript<p><b>Use case for boot-cljs and boot-reload:</b></p>
<p>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 <tt>:js-dependency-index</tt> to build the graph: <a href="https://github.com/adzerk-oss/boot-cljs/blob/0.0-3308/src/adzerk/boot_cljs/impl.clj#L17-L36">https://github.com/adzerk-oss/boot-cljs/blob/0.0-3308/src/adzerk/boot_cljs/impl.clj#L17-L36</a></p>
<p><b>Simple solution:</b></p>
<p>If dependencies (requires) of namespace are exposed through API it is easy to build graph of cljs namespace dependencies: <a href="https://github.com/adzerk-oss/boot-cljs/blob/d479f10935be321232e2363e2ae3e9cc515a81af/src/adzerk/boot_cljs/impl.clj#L12-L32">https://github.com/adzerk-oss/boot-cljs/blob/d479f10935be321232e2363e2ae3e9cc515a81af/src/adzerk/boot_cljs/impl.clj#L12-L32</a></p>
<p>Problem with this solution is that <tt>all-ns</tt>, <tt>ns-dependencies</tt> or <tt>target-file-for-cljs-ns</tt> 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.</p>
<p><b>Questions, notes and issues</b></p>
<ul class="alternate" type="square">
<li>Should <tt>cljs-dependency-graph</tt> be exposed in the API or is it enough to provide <tt>ns-dependencies</tt> and such which user can use to create dependency graph?</li>
<li><tt>cljs.build.api/parse-js-ns</tt> can also be used to read provides and requires from compiled JS files, but this doesn't work with foreign-deps either</li>
<li>Perhaps there is some way in Closure library to reload files in correct order?</li>
<li>Supporting foreign-deps is not perhaps necessary, but if there is good way it would be nice to have.</li>
</ul>
CLJS-1407Exposing output file dependency graph in APIEnhancementMinorOpenUnresolvedUnassignedJuho TeperiSun, 9 Aug 2015 08:11:03 -0500Sun, 8 Nov 2015 09:28:54 -060001<p>I would add the call to <tt>cljs.compiler.api</tt> and it could be called <tt>output-dependency-graph</tt>.</p>
<p>Creating the graph requires list of all the nodes and dependencies for each node. For Cljs namespaces<br/>
these are accessible through <tt>all-ns</tt> and ns analysis map <tt>:requires</tt>. Data about foreign-deps<br/>
and closure libs is available in the compiler state under <tt>:js-dependency-index</tt> key. To create the<br/>
graph we need to:</p>
<p>1. Get list of all nodes<br/>
2. Get dependencies for given node<br/>
3. Get output file for given node</p>
<p>Because steps 2 and 3 depend on the type of node, it would probably be easiest to collect those<br/>
values in step 1. So step 1 would do something like this:</p>
<p>{{(get-nodes ...) =&gt; <a href="#{&quot;goog.foo&quot;}} {:provides &quot;frontend.core&quot; :file &quot;out/frontend/core.js&quot; :dependencies #{&quot;cljs.core&quot;}}">{:provides "goog.net" :file "out/goog/net.js" :dependencies #{"goog.foo"}} {:provides "frontend.core" :file "out/frontend/core.js" :dependencies #{"cljs.core"}}</a>}}</p>
<p>That could be implemented by concatenating data from cljs namespaces retrieved from <tt>all-ns</tt> etc. with<br/>
data from <tt>:js-dependency-index</tt>. The next and last step would be to construct the graph using reduce.</p>
<p>Using this implementation there would be just one new API call: <tt>output-dependency-graph</tt>.</p>
<p>I was thinking alternative approach with <tt>all-ns</tt>, <tt>find-ns</tt> 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.</p><p>Now that <a href="http://dev.clojure.org/jira/browse/CLJS-1437" title="Recompile dependents broken when files are not inside one directory"><del>CLJS-1437</del></a> is merged what is needed to wrap this one up?</p><p>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?</p><p>It may still be useful at some point. Will just lower the priority.</p>Global Rank[CLJS-1502] Browser REPL broken when started with :optimizations :nonehttp://dev.clojure.org/jira/browse/CLJS-1502
ClojureScript<p>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.<br/>
:optimizations :simple (the default) works fine.<br/>
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.</p>CLJS-1502Browser REPL broken when started with :optimizations :noneDefectMinorOpenUnresolvedUnassignedewen grosjeanSat, 5 Dec 2015 16:53:48 -0600Sun, 6 Dec 2015 06:54:47 -060000Global RankPatchCode[CLJS-1513] Javascript emitted for cljs.pprint is misinterpreted under Mobile Safari 7.0http://dev.clojure.org/jira/browse/CLJS-1513
ClojureScript<p>Create minimal ClojureScript project, add {{(:require [cljs.pprint :refer <span class="error">&#91;pprint&#93;</span>])}} to the source file and compile with <tt>:optimizations :advanced</tt>. Output js will contain strings like <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">~\x3c\x3c-(~;~@{~w~^ ~_~}~;)-\x3c~:\x3e</pre>
</div></div> which lead to the following error in the Mobile Safari 7.0:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Error: Directive <span class="code-quote">"{"</span> is undefined
~&lt;&lt;-(~;~@{~w~^ ~_~}~;)-&lt;~:&gt;
^</pre>
</div></div>Tested with 1.7.28 and 1.7.170 versions of ClojureScript.
<br/>
<br/>
browser = Mobile Safari 7.0
<br/>
os = iOS 7.1.2CLJS-1513Javascript emitted for cljs.pprint is misinterpreted under Mobile Safari 7.0DefectMinorOpenUnresolvedUnassignedRuslan ProkopchukMon, 14 Dec 2015 07:37:44 -0600Mon, 14 Dec 2015 08:54:43 -06001.7.2800Global Rank[CLJS-1104] Compute SHA for ClojureScript compiled filehttp://dev.clojure.org/jira/browse/CLJS-1104
ClojureScript<p>Needed for shared AOT cache</p>CLJS-1104Compute SHA for ClojureScript compiled fileDefectMinorOpenUnresolvedUnassignedDavid NolenTue, 10 Mar 2015 08:46:13 -0500Tue, 22 Dec 2015 16:53:43 -060000Global Rank[CLJS-1075] Generic inline source map supporthttp://dev.clojure.org/jira/browse/CLJS-1075
ClojureScript<p>Currently hard coded to REPLs. Would simplify jsbin and similar integration.</p>CLJS-1075Generic inline source map supportEnhancementMinorOpenUnresolvedUnassignedDavid NolenMon, 2 Mar 2015 14:15:38 -0600Tue, 22 Dec 2015 17:01:26 -060000Global Rank[CLJS-575] cljsc.bat emit FileNotFoundException when compile samples in windowshttp://dev.clojure.org/jira/browse/CLJS-575
ClojureScript<p>cljsc.bat emit FileNotFoundException when it compile samples of the ClojureScript project in windows like below.</p>
<p>------------------------------------------------<br/>
Exception in thread "main" java.io.FileNotFoundException: Could not locate cljs/closure__init.class<br/>
or cljs/closure.clj on classpath:<br/>
------------------------------------------------</p>
<p>It is caused by lack of a backslash in the end of path of the system environment variable, %CLOJURESCRIPT_HOME% set by a user.<br/>
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.</p>
<p>So it can be solved by adding a backslash to the path of %CLOJURESCRIPT_HOME%.</p>
<p>I attached the patched file, "cljsc-path.bat"</p>in windows 7CLJS-575cljsc.bat emit FileNotFoundException when compile samples in windowsDefectMinorOpenUnresolvedUnassignedPark Sang KyuCompilerbugpatchSun, 25 Aug 2013 01:13:55 -0500Tue, 5 Jan 2016 16:36:18 -060001<p>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.</p><p>git diff</p><p>Thank you! Have you sent in your CA? <a href="http://clojure.org/contributing">http://clojure.org/contributing</a></p><p>Yes i have sent my CA.</p><p>Excellent, the patch is not correctly formatted. Can we get a new patch that conforms to <a href="http://github.com/clojure/clojurescript/wiki/Patches">http://github.com/clojure/clojurescript/wiki/Patches</a></p>Global RankPatchCode[CLJS-1548] cannot reference a JS global var with same name as current namespacehttp://dev.clojure.org/jira/browse/CLJS-1548
ClojureScript<p>Steps to reproduce:</p>
<p>1. Create a JS global var `foo`.<br/>
2. Create a `foo.core` namespace.<br/>
3. Try referencing `js/foo` in `foo.core`.</p>
<p>Problem:</p>
<p>`js/foo` does not resolve to the JS global var `foo`<br/>
(in advanced optimizations, but not w/ optimizations off).</p>
<p>Solution: Proposing we issue a warning.</p>
<p>Will put together a diagnostic project soon and see about working on a patch.</p>CLJS-1548cannot reference a JS global var with same name as current namespaceDefectMinorOpenUnresolvedUnassignedShaun LeBronTue, 19 Jan 2016 10:14:46 -0600Tue, 19 Jan 2016 10:14:46 -060000Global Rank[CLJS-1059] Simple interface wanted to convert cljs forms to jshttp://dev.clojure.org/jira/browse/CLJS-1059
ClojureScript<p>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.</p>
<p>We would like something similar to closure/compile-form-seq (<a href="https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L308">https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L308</a>)</p>
<p>However, we need to supply, the namespace requires and locals in an env like this</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">{:ns {:name <span class="code-quote">"test.core"</span> :requires {(quote gstring) (quote goog.string)}} :locals {}}</pre>
</div></div>
<p>This code seems to do what we want.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn compile-form-seq
\<span class="code-quote">"Compile a sequence of forms to a JavaScript source string.\"</span>
[forms env]
(env/ensure
(compiler/with-core-cljs nil
(fn []
(with-out-str
(doseq [form forms]
(compiler/emit (analyzer/analyze env form))))))))</pre>
</div></div>
<p>I am not sure why I need env/ensure.</p>
<p>Would you be able to patch compile-form-seq to provide the needed interface, or suggest what we should be doing.</p>
<p>Thanks<br/>
Stu</p>CLJS-1059Simple interface wanted to convert cljs forms to jsEnhancementMinorOpenUnresolvedUnassignedStuart MitchellanalyzercompilerSun, 22 Feb 2015 21:38:52 -0600Sun, 31 Jan 2016 15:11:29 -06000.0-321101
<p>Just to be clear: <br/>
1. when our debugger is at a breakpoint, <br/>
2. the user can type in an expression at the repl<br/>
3. in response, our debugger has to compile the user-typed-in expression to javascript (and then execute it, showing a result)<br/>
4. taking into account any local bindings. &lt;---- this is the key bit. </p>
<p>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.</p>
<p>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'</p>
<p>Our method to achieve this is to put 'x' into env/locals when compiling &#8211; 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. </p><p>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,...</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(fn [x]
~user-expression-here)</pre>
</div></div><p>Seems like something useful to add to a <tt>cljs.compiler.api</tt> namespace.</p>Global Rank[CLJS-651] optimize true branch of satisfies? usagehttp://dev.clojure.org/jira/browse/CLJS-651
ClojureScript<p>The true branch of a satisfies? test should be hinted so that the type doesn't need type hints</p>CLJS-651optimize true branch of satisfies? usageEnhancementMinorOpenUnresolvedUnassignedDavid NolenFri, 1 Nov 2013 12:28:12 -0500Sun, 31 Jan 2016 15:26:57 -060001<p>All paths taken on satisfies are now hinted as boolean</p><p>cljs_651.patch no longer applies on master</p>Global RankPatchCode[CLJS-1458] re-matches might give false negative when using match groupshttp://dev.clojure.org/jira/browse/CLJS-1458
ClojureScript<p>Current behaviour:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(re-matches #<span class="code-quote">"(a|aa)"</span> <span class="code-quote">"aa"</span>) =&gt; nil</pre>
</div></div>
<p>Expected:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(re-matches #<span class="code-quote">"(a|aa)"</span> <span class="code-quote">"aa"</span>) =&gt; [<span class="code-quote">"aa"</span> <span class="code-quote">"aa"</span>]</pre>
</div></div>
<p>JVM version works as expected, only CLJS is affected</p>CLJS-1458re-matches might give false negative when using match groupsDefectMinorOpenUnresolvedUnassignedNikita ProkopovFri, 25 Sep 2015 06:34:55 -0500Sun, 31 Jan 2016 15:45:47 -060002<p>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.</p><p>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).</p>Global RankPatchCode and Test[CLJS-1559] Closure :libs ignoredhttp://dev.clojure.org/jira/browse/CLJS-1559
ClojureScript<p>: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.</p>
<p>Compilation options:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(cljs.closure/build
<span class="code-quote">"src/main/clojurescript"</span>
{:main 'example.core
:libs [<span class="code-quote">"/src/main/javascript/"</span>]
:optimizations :none
:output-dir <span class="code-quote">"js"</span>
:output-to <span class="code-quote">"js/main.js"</span>
:source-map <span class="code-keyword">true</span>
:asset-path <span class="code-quote">"/js"</span>
})</pre>
</div></div>
<p>Javascript file:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">goog.provide(<span class="code-quote">"test.Test"</span>);
test.Test = function(x) {
<span class="code-keyword">this</span>.x = x;
};</pre>
</div></div>CLJS-1559Closure :libs ignoredDefectMinorOpenUnresolvedUnassignedDominykas MostauskisFri, 5 Feb 2016 12:38:01 -0600Fri, 5 Feb 2016 15:50:22 -06001.7.22801<p>Hi Dominykas, is the absolute path intentional? I suspect the intent was to not have the leading <tt>/</tt>.</p><p>I made this typo when posting. On my setup paths are relative to project root.</p><p>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.</p><p>Can't reproduce. Tips would be appreciated. Banging my head against the wall here.</p>Global Rank[CLJS-1153] Typed Array backed PersistentVector based on clojure.core/Vechttp://dev.clojure.org/jira/browse/CLJS-1153
ClojureScript<p>Goal is to add support for vectors based on clojure.core/Vec, built on top of JavaScript Typed Arrays. </p>
<p>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. </p>
<p>Implementation is based heavily on clojure/core/gvec.clj, cljs.core/PersistentVector, and cljs.core/TransientVector. </p>
<p>Performance should be comparable to cljs.core/PersistentVector, although there is additional constant overhead with TypedArray instantiation compared to js/Array. </p>
<p>Adds cljs.core/Vec, cljs.core/TransientVec, cljs.core/vector-of, and updates cljs.core/into-array. </p>CLJS-1153Typed Array backed PersistentVector based on clojure.core/VecEnhancementMinorOpenUnresolvedUnassignedAdrian MedinaenhancementThu, 19 Mar 2015 20:34:52 -0500Fri, 5 Feb 2016 20:18:06 -060013<p>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. </p><p>No mention of Uint8ClampedArray.</p>
<p>Should Vec type- or range-check assignments? In Clojure these fail (even with unchecked-math):</p>
<ul>
<li>(vector-of :byte 128) returns <span class="error">&#91;-128&#93;</span></li>
<li>(vector-of :byte "1") returns <span class="error">&#91;1&#93;</span></li>
<li>(vector-of :byte (js-obj)) returns <span class="error">&#91;0&#93;</span></li>
</ul>
<p>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 <tt>into-array</tt>? Some or all of these issues may warrant another ticket instead, or maybe even a design page:</p>
<ul>
<li>make-array ignores type argument and lacks higher dimensions.</li>
<li>object-array, int-array, etc. maybe should return TypedArrays.</li>
<li>Missing ubyte-array, ushort-array, uint-array (like ClojureCLR)</li>
<li>Missing aset-* setters. (Meaningless in js unless we range-check.)</li>
<li>aclone and amap preserve type of input array in Clojure, but not in cljs.</li>
<li>missing array casters: bytes, shorts, chars, ints, etc.</li>
<li>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?</li>
</ul>
<p>Patch 1153.patch no longer applies</p>Global RankPatchCode[CLJS-776] re-matches is incorrecthttp://dev.clojure.org/jira/browse/CLJS-776
ClojureScript<p>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.</p>
<p>Example in Clojure:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">user=&gt; (re-find #<span class="code-quote">"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+"</span> <span class="code-quote">"0x1"</span>)
<span class="code-quote">"0"</span>
user=&gt; (re-matches #<span class="code-quote">"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+"</span> <span class="code-quote">"0x1"</span>)
<span class="code-quote">"0x1"</span></pre>
</div></div>
<p>Compare Clojurescript:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (re-find #<span class="code-quote">"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+"</span> <span class="code-quote">"0x1"</span>)
<span class="code-quote">"0"</span>
ClojureScript:cljs.user&gt; (re-matches #<span class="code-quote">"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+"</span> <span class="code-quote">"0x1"</span>)
nil</pre>
</div></div>
<p>This bug is (one of the) reasons why <a href="http://dev.clojure.org/jira/browse/CLJS-775" title="cljs.reader parses radix form of int literals (e.g. 2r101) incorrectly "><del>CLJS-775</del></a>.</p>
<p>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.</p>
<p>Questions:</p>
<ol>
<li>Are there any valid patterns where this is not safe? E.g., where we could not put ^ first? Is "^^abc$$" ok?</li>
<li>Can we avoid cloning if ^ and $ are already the first and last chars of the pattern?</li>
<li>How does multiline mode play in to this, if at all?</li>
<li>regexinstance.lastIndex is a piece of mutability on regex instances (or the RegExp global<img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/warning.gif" height="16" width="16" align="absmiddle" alt="" border="0"/> 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 <a href="http://dev.clojure.org/jira/browse/CLJS-150" title="Regular expressions don&#39;t support Javascript mode flags">CLJS-150</a>: allowing clojure to accept the global flag makes regular expression objects stateful, and would completely screw up re-seq for example.)</li>
</ol>
CLJS-776re-matches is incorrectDefectMinorOpenUnresolvedUnassignedFrancis AvilaFri, 28 Feb 2014 01:04:14 -0600Tue, 2 Dec 2014 13:16:57 -060003<p>I would like to propose a somewhat radical suggestion that would: fix this issue and <a href="http://dev.clojure.org/jira/browse/CLJS-810" title="re-matches returns [] if string is nil"><del>CLJS-810</del></a>, put us in a better position to resolve <a href="http://dev.clojure.org/jira/browse/CLJS-485" title="clojure.string/replace ignores regex flags">CLJS-485</a> <a href="http://dev.clojure.org/jira/browse/CLJS-746" title="clojure.string/replace pattern/function of match API difference with clojure version">CLJS-746</a> <a href="http://dev.clojure.org/jira/browse/CLJS-794" title="RegExp flags are being dropped by `string/replace`">CLJS-794</a> (clojure.string/replace woes), allow us to add some regex-as-a-value niceties to patterns in js (<a href="http://dev.clojure.org/jira/browse/CLJS-67" title="IHash implementation for regular expressions."><del>CLJS-67</del></a> and <a href="http://dev.clojure.org/jira/browse/CLJS-68" title="IEquiv implementation for regular expressions."><del>CLJS-68</del></a>), and bring clojurescript's regular expression handling closer to clojure's by implementing more of the re-* functions.</p>
<p>Example implementation (not a patch) at this cljsfiddle: <a href="http://cljsfiddle.net/fiddle/favila.regexp">http://cljsfiddle.net/fiddle/favila.regexp</a></p>
<p>Essential points:</p>
<ol>
<li>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.</li>
<li>regular expression literals emit these Pattern objects instead of RegExp objects.</li>
<li>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.</li>
<li>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.)</li>
<li>If re-find is given a native RegExp object instead of a pattern, it will use it as-is. This matches current behavior.</li>
<li>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.)</li>
</ol>
<p>Thoughts?</p><p>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?</p><p>I apologize if some of my thoughts are vague; I haven't thought about this in a while.</p>
<p>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.</p>
<p>Interop possibilities:</p>
<ul>
<li>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.)</li>
<li>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.)</li>
<li>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?</li>
<li>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:
<ul>
<li>Matcher holds the matched string in Java. Javascript trusts you to always supply the same string (e.g. in a while loop).</li>
<li>Java's Matcher holds the last match (used by re-groups). Javascript's RegExp does not.</li>
<li>Javascript's RegExp will automatically reset when lastIndex reaches the end of the source string. Java's Matcher won't.</li>
<li>Matcher must be a wrapper and not a normal RegExp because of these three extra bits of state.</li>
<li>The return value of re-matcher is only consumed by the 1-arg form of re-find and re-groups.</li>
<li>re-seq can use a matcher internally, but since it is private it doesn't have to.</li>
<li>Should other Java methods of Matcher be implemented?</li>
</ul>
</li>
<li>Pattern given to String.prototype.match, .replace, .search, and .split: I haven't thought about this. Considerations:
<ul>
<li>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.</li>
<li>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.</li>
<li>The fix for such code is to either:
<ul>
<li>Use a pattern-&gt;regexp coercion function we will provide.</li>
<li>Construct those regexps directly with js/RegExp.</li>
<li>Use clojure.string functions instead of String methods. This also has the advantage of being portable between clj and cljs.</li>
</ul>
</li>
<li>Possibly we can patch the RegExp constructor or mess with the String prototype chain to do pattern-&gt;regexp coercion automatically, but this is a violent solution.</li>
</ul>
</li>
</ul>
<p>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. </p>Global Rank[CLJS-1599] UUIDs are not equal for upper/lower case stringshttp://dev.clojure.org/jira/browse/CLJS-1599
ClojureScript<p>UUIDs generated for strings in different case (one is upper and one is lower) are equal.</p>
<p>For example <tt>(= (uuid "071C600F-B72B-44AE-8A15-9366EA1BB9D9") (uuid "071c600f-b72b-44ae-8a15-9366ea1bb9d9"))</tt> returns <tt>false</tt>.</p>
<p>Spec <a href="http://www.itu.int/rec/T-REC-X.667/en">http://www.itu.int/rec/T-REC-X.667/en</a> says following:</p>
<p>6.5.4 Software generating the hexadecimal representation of a UUID shall not use upper case letters.<br/>
NOTE - It is recommended that the hexadecimal representation used in all human-readable formats be restricted to lower-case<br/>
letters. Software processing this representation is, however, required to accept both upper and lower case letters as specified<br/>
in 6.5.2.</p>Windows 7x64CLJS-1599UUIDs are not equal for upper/lower case stringsDefectMinorOpenUnresolvedUnassignedNikolay DuryginMon, 7 Mar 2016 02:04:34 -0600Fri, 11 Mar 2016 13:00:31 -06001.7.22800<p>Would this be a good time to change the internal representation from a string to either a pair of goog.math.Longs or a quartet of "32-bit" integer doubles?</p><p>Is there any special need? Issue described above can be solved by lower casing all strings inside <tt>uuid</tt>. Another problem - the fact that <tt>uuid</tt> doesn't complain if non uuid format string is passed can be solved with regex.</p>Global Rank[CLJS-1444] Node.js shim requires `node` invocation to be in the same directory as shim scripthttp://dev.clojure.org/jira/browse/CLJS-1444
ClojureScript<p>Don't have time to provide a proper repro now but the basic issue can be illustrated by this:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">~/c/boot-cljs-example (master=) node target/main.js
module.js:338
<span class="code-keyword">throw</span> 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 <span class="code-object">Object</span>.&lt;anonymous&gt; (/Users/martin/code/boot-cljs-example/target/main.js:6:1)
at Module._compile (module.js:460:26)
at <span class="code-object">Object</span>.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...</pre>
</div></div>
<p>This is compiled with boot because that was what I had at hand right now. The compiled shim looks like this:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript"><span class="code-keyword">var</span> path = require("path");
<span class="code-keyword">try</span> {
require("source-map-support").install();
} <span class="code-keyword">catch</span>(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");</pre>
</div></div>
<p>The problem here is that <tt>path.resolve(".")</tt> will return the directory the <tt>node</tt> command was invoked in and not the directory of the shim. (See the "Cannot find module..." error above)</p>
<p>A solution could be to use <tt>__dirname</tt> which always resolves to the directory of the current file. This might result in some breakage for existing setups.</p>CLJS-1444Node.js shim requires `node` invocation to be in the same directory as shim scriptDefectMinorOpenUnresolvedUnassignedMartin KlepschThu, 10 Sep 2015 08:24:14 -0500Mon, 14 Mar 2016 10:43:23 -050001<p>I have a proposed solution but I fear that supporting "run from anywhere" adds essential complexity to the resulting code. My thought process:</p>
<p>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") .</p>
<p>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.</p>
<p>3. The frame of reference is not explicit anywhere in the code, since it is defined as <tt>"."</tt>. If it were explicit, it would reveal context, as in <tt>"/home/some-user/their-folder/this-project/"</tt>.</p>
<p>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.</p>
<p>Path algebra:<br/>
<tt>compiler-path = __dirname - output-to</tt></p>
<p>Node.js</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">var</span> compiler-path = __dirname.replace(output-to, "")
path.resolve (compiler-path, output-dir, <span class="code-quote">"goog"</span>, <span class="code-quote">"base.js"</span>)
path.resolve (compiler-path, output-dir, <span class="code-quote">"cljs_deps.js"</span>)</pre>
</div></div>
<p>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.</p>
<p>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.</p><p>I find this behavior really weird and would opt for switching to <tt>__dirname</tt>. I am also not sure i fully understand consequences of such switch (I have little cljs experience, speaking more from the perspective of nodejs user). My point is: current behavior renders clojurescript hard to use for commandline and desktop applications (namely electron).</p>
<p>For command line and desktop applications assumptions about CWD cannot be made. For now i run my applications through a bootstrap script JS script:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">process.chdir(__dirname);
require('./target/out');</pre>
</div></div>
<p>I am lucky that my code does not have to use the real CWD, but it's a hack more than a real solution.</p>
<p>Speaking from nodejs perspective:</p>
<p>1. Using absolute paths is considered a bad practice anyway.<br/>
2. Nodejs programs that don't use external packages (don't depend on <b>node_modules</b>) can be run from any CWD<br/>
3. Nodejs programs that do depend on <b>node_modules</b> will break if run from a different directory than the one containing <b>node_modules</b>, but this is expected behavior.</p>
Global Rank[CLJS-1575] Combination of - and _ params causes JSC_DUPLICATE_PARAMhttp://dev.clojure.org/jira/browse/CLJS-1575
ClojureScript<p>The following function definitions each cause <tt>ERROR: JSC_DUPLICATE_PARAM. Parse error. Duplicate parameter name "_"</tt> at compile time with <tt>:advanced</tt> compilation:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div class="error"><span class="error">Unable to find source-code formatter for language: clojure.</span> Available languages are: javascript, sql, xhtml, actionscript, none, html, xml, java</div><pre class="code-clojure">(defn causes-duplicate-param [{_ :foo}]
(reify
<span class="code-object">Object</span>
(a-function [-]
(fn [] <span class="code-quote">"arbitrary function inside a-function body"</span>))))
(defn causes-duplicate-param [{- :foo}]
(reify
<span class="code-object">Object</span>
(a-function [_]
(fn [] <span class="code-quote">"arbitrary function inside a-function body"</span>))))</pre>
</div></div>
<p>They generate, respectively:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript">duplicate_param_name_demo.core.t_duplicate_param_name_demo$core1601.prototype.a_function = ((<span class="code-keyword">function</span> (map__1599,map__1599__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">var</span> self__ = <span class="code-keyword">this</span>;
<span class="code-keyword">var</span> _ = <span class="code-keyword">this</span>;
<span class="code-keyword">return</span> ((<span class="code-keyword">function</span> (_,map__1599,map__1599__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">return</span> "arbitrary <span class="code-keyword">function</span> inside a-<span class="code-keyword">function</span> body";
});
;})(_,map__1599,map__1599__$1,_))
});})(map__1599,map__1599__$1,_))
;
duplicate_param_name_demo.core.t_duplicate_param_name_demo$core1612.prototype.a_function = ((<span class="code-keyword">function</span> (map__1610,map__1610__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">var</span> self__ = <span class="code-keyword">this</span>;
<span class="code-keyword">var</span> _ = <span class="code-keyword">this</span>;
<span class="code-keyword">return</span> ((<span class="code-keyword">function</span> (_,map__1610,map__1610__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">return</span> "arbitrary <span class="code-keyword">function</span> inside a-<span class="code-keyword">function</span> body";
});
;})(_,map__1610,map__1610__$1,_))
});})(map__1610,map__1610__$1,_))
;</pre>
</div></div>
<p>(Notice the duplicate <tt>_</tt> param on the 5th line of each.)</p>
<p>The following do not:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div class="error"><span class="error">Unable to find source-code formatter for language: clojure.</span> Available languages are: javascript, sql, xhtml, actionscript, none, html, xml, java</div><pre class="code-clojure">(defn causes-duplicate-param [{- :foo}]
(reify
<span class="code-object">Object</span>
(a-function [-]
(fn [] <span class="code-quote">"arbitrary function inside a-function body"</span>))))
(defn causes-duplicate-param [{_ :foo}]
(reify
<span class="code-object">Object</span>
(a-function [_]
(fn [] <span class="code-quote">"arbitrary function inside a-function body"</span>))))</pre>
</div></div>
<p>They generate:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript">duplicate_param_name_demo.core.t_duplicate_param_name_demo$core1601.prototype.a_function = ((<span class="code-keyword">function</span> (map__1599,map__1599__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">var</span> self__ = <span class="code-keyword">this</span>;
<span class="code-keyword">var</span> ___$1 = <span class="code-keyword">this</span>;
<span class="code-keyword">return</span> ((<span class="code-keyword">function</span> (___$1,map__1599,map__1599__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">return</span> "arbitrary <span class="code-keyword">function</span> inside a-<span class="code-keyword">function</span> body";
});
;})(___$1,map__1599,map__1599__$1,_))
});})(map__1599,map__1599__$1,_))
;
duplicate_param_name_demo.core.t_duplicate_param_name_demo$core1612.prototype.a_function = ((<span class="code-keyword">function</span> (map__1610,map__1610__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">var</span> self__ = <span class="code-keyword">this</span>;
<span class="code-keyword">var</span> ___$1 = <span class="code-keyword">this</span>;
<span class="code-keyword">return</span> ((<span class="code-keyword">function</span> (___$1,map__1610,map__1610__$1,_){
<span class="code-keyword">return</span> (<span class="code-keyword">function</span> (){
<span class="code-keyword">return</span> "arbitrary <span class="code-keyword">function</span> inside a-<span class="code-keyword">function</span> body";
});
;})(___$1,map__1610,map__1610__$1,_))
});})(map__1610,map__1610__$1,_))
;</pre>
</div></div>
<p>(Notice that one of the {<em>} params has become <tt></em>__$1</tt>.)</p>
<p>My guess, though I haven't looked into the compiler code, is that the compiler escapes {<em>} to <tt></em>_<em>$1</tt> when it would conflict with another {</em>}, and also it translates <tt>-</tt> to {<em>}, but it doesn't notice the conflict when the _ClojureScript</em> symbols are different.</p>CLJS-1575Combination of - and _ params causes JSC_DUPLICATE_PARAMDefectMinorOpenUnresolvedUnassignedPeter JarosWed, 17 Feb 2016 11:42:40 -0600Fri, 18 Mar 2016 13:46:15 -050001<p>Forgive the weird formatting errors. I couldn't find a preview function and there doesn't appear to be a way to edit the issue now that it's posted.</p><p>This is because of munging they will become the same thing. Patch welcome.</p>Global Rank[CLJS-1610] Refs apihttp://dev.clojure.org/jira/browse/CLJS-1610
ClojureScript<p>It would be nice to support the refs API in clojurescript to ease porting of libraries which require it. Obviously usage of it would not bring concurrency benefits, but it would at least allow some existing clojure code to run.</p>
<p>I've satisfied myself it can be done reasonably easily (see <a href="https://github.com/jjl/clojurescript/tree/ref-support">https://github.com/jjl/clojurescript/tree/ref-support</a> ), and I can't really see any downsides.</p>
<p>For the minute, this has been put into the cljs.stm namespace. I don't know whether it should be a feature you are automatically opted into, so I didn't put it into core. Thoughts?</p>CLJS-1610Refs apiEnhancementMinorOpenUnresolvedUnassignedJames LaverSat, 26 Mar 2016 15:10:02 -0500Mon, 28 Mar 2016 06:44:18 -050001<p>It's definitely worth considering. If you've done the work, attach an actual patch for review. In general we try to avoid links outside.</p>Global Rank[CLJS-1574] CLJS string equivalence is very slow in Chromehttp://dev.clojure.org/jira/browse/CLJS-1574
ClojureScript<p>Clojurescript's equivalence for strings in Google Chrome is ~1000 times slower than equivalent javascript functionality, and ~1000 times slower than the same function in Safari.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Google Chrome</b></div><div class="codeContent panelContent">
<pre class="code-java">js equiv: 0.005 seconds
cljs equiv: 1.898 seconds</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Safari</b></div><div class="codeContent panelContent">
<pre class="code-java">js equiv: 0.005 seconds
cljs equiv: 0.006 seconds</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def size (* 128 1024))
(defn now []
(.getTime (js/Date.)))
(defn delta [b a]
(str (/ (- b a) 1000) <span class="code-quote">" seconds"</span>))
(deftest test-js-eq-perf
(let [str1 (apply str (repeat size <span class="code-quote">"a"</span>))
str2 (apply str (repeat size <span class="code-quote">"a"</span>))
start (now)
_ (is (js* <span class="code-quote">"~{} == ~{}"</span> str1 str2)
<span class="code-quote">"js equivalence"</span>)
end (now)
]
(println <span class="code-quote">"js equiv: "</span> (delta end start))))
(deftest test-cljs-eq-perf
(let [str1 (apply str (repeat size <span class="code-quote">"a"</span>))
str2 (apply str (repeat size <span class="code-quote">"a"</span>))
start (now)
_ (is (= str1 str2)
<span class="code-quote">"cljs equivalence"</span>)
end (now)
]
(println <span class="code-quote">"cljs equiv: "</span> (delta end start))))</pre>
</div></div>Google Chrome 48.0.2564.109 on Mac OS X 10.11.3
<br/>
Safari 9.0.3 (11601.4.4) on Mac OS X 10.11.3CLJS-1574CLJS string equivalence is very slow in ChromeDefectMinorOpenUnresolvedUnassignedStephen NelsonperformanceTue, 16 Feb 2016 15:34:23 -0600Mon, 22 Feb 2016 03:14:42 -06001.7.22802<p>This bug only occurs when cljs.pprint has been required.</p><p>After a whole lot of binary search, here's a minimal reproduction. When cljs.pprint is loaded it constructs <tt>write-option-table</tt>. It seems that constructing a hash map with the keys <tt>:added</tt> and <tt>:ns</tt> causes a call to <tt>(= :added :ns)</tt>, which is sufficient to cause string equality to become extremely slow.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns hello-world.core)
(enable-console-print!)
(def size (* 128 1024))
(defn now []
(.getTime (js/Date.)))
(defn delta [b a]
(str (/ (- b a) 1000) <span class="code-quote">" seconds"</span>))
(defn test []
(let [str1 (apply str (repeat size <span class="code-quote">"a"</span>))
str2 (apply str (repeat size <span class="code-quote">"a"</span>))
start (now)
_ (= str1 str2)
end (now)
]
(println <span class="code-quote">"cljs equiv: "</span> (delta end start))))
(test)
(= :added :ns)
(test)</pre>
</div></div><p>Is the ClojureScript compiled with options :optimizations :advanced or :static-fns true? Compiling ClojureScript without those options results in call indirection for all function calls which might explain the slowdown. See <a href="http://swannodette.github.io/2015/03/16/optimizing-clojurescript-function-invocation/">http://swannodette.github.io/2015/03/16/optimizing-clojurescript-function-invocation/</a> for more information.</p><p>This happens with <tt>:advanced</tt>, <tt>:simple</tt>, and without optimisations. Stepping through the generated javascript seems to indicated that the slow down comes from the VM's internal function dispatch. Regardless, I don't think that the extra function calls related to dynamic dispatch in clojurescript could add minutes of overhead per call. Note that the test case above only uses 128k of string data, the case where I encountered this issue first used ~512K and took about 5 minutes to complete a single function call.</p><p>I have reproduced this in Chrome for Linux, on :none and :advanced optimization levels using different test code. I verified the result of the compare so the JIT won't optimize it away and I used <tt>performance.mark()</tt> and <tt>performance.measure()</tt> for timing, although none of this should have mattered.</p>
<p>Every subsequent string compare after the first <tt>&#45;equiv</tt>&#45;invoking use of equal is significantly slower for no reason I can see. There are no intermediate GCs or anything to suggest that it should be slower--it just takes longer! The only thing I can think of is maybe the keyword-equals triggers a deopt because it makes the equal-function megamorphic, but the code is run so few times that there should not be jit optimizations kicking it at all. Also, the keyword-compare itself remains fast.</p>
<p>I suspect a Chrome/v8 bug. Possibly a different internal string representation kicks in for some reason which has a slower compare? This is only an issue for largish, non-constant strings, and the slowdown is proportional to string size. I'm going to try and reproduce this with pure JS.</p>
<p>All you need to reproduce this is to use the strict equality operator in a function body non-monomorphically. Subsequent executions of the function with strings (at least) which have not been compared <b>before the polymorphic call</b> will be very slow.</p>
<p>If you replace strict equality (triple-equal) with normal equality (double-equal), this issue goes away.</p>
<p>This is clearly a Chrome/v8 bug, but I'm not sure where to report it.</p>
<p>Minimal pure-javascript reproduction:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-javascript"><span class="code-keyword">function</span> str(size) {
<span class="code-keyword">var</span> s = "";
<span class="code-keyword">for</span> (<span class="code-keyword">var</span> i = 0; i &lt; size; i++) s += "a";
<span class="code-keyword">return</span> s;
}
<span class="code-keyword">function</span> eq(x, y) {
performance.mark("start");
x === y; // No slowdown <span class="code-keyword">if</span> use == instead
performance.mark("end");
}
<span class="code-keyword">function</span> print_measures() {
performance.getEntriesByType("measure")
.forEach(entry =&gt; console.log(entry.name, entry.duration));
}
<span class="code-keyword">var</span> s1 = str(64 * 1024);
<span class="code-keyword">var</span> s2 = str(64 * 1024);
<span class="code-keyword">var</span> s3 = str(64 * 1024);
eq(s1, s2);
performance.measure("eq(s1, s2)", "start", "end");
eq(0, 0);
performance.measure("eq(0, 0)", "start", "end");
eq(s1, s3);
performance.measure("eq(s1, s3)", "start", "end");
eq(s1, s2);
performance.measure("eq(s1, s2)", "start", "end");
eq(s1, s3);
performance.measure("eq(s1, s3)", "start", "end");
print_measures();</pre>
</div></div>
<p>Results with Chrome 48.0.2564.109 (64-bit) on a slow iMac with OS X 10.11.3</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-none">eq(s1, s2) 4.465000000000003 // fast string compare
eq(0, 0) 0.009999999999990905 // break monomorphism of eq()
eq(s1, s3) 259.665 // Now string compare is slow
eq(s1, s2) 0.019999999999924967 // Repeated call still fast
eq(s1, s3) 232.52499999999998 // ... but not from after the polymorphic invoke</pre>
</div></div><p>Issue added to v8: <a href="https://bugs.chromium.org/p/v8/issues/detail?id=4773">https://bugs.chromium.org/p/v8/issues/detail?id=4773</a></p>Global Rank[CLJS-1620] In JavaScript ES2015 modules default export name is munged to default$http://dev.clojure.org/jira/browse/CLJS-1620
ClojureScript<p>When using a foreign lib which is ES2015 module with default export, the value which is being exported is assigned to a property <tt>default</tt> on a namespace object. In ClojureScript code this means one should call to <tt>default</tt> var of that namespace. However in complied output of ClojureScript code the name <tt>default</tt> is getting munged to <tt>default$</tt>.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">export <span class="code-keyword">default</span> function inc(v) {
<span class="code-keyword">return</span> v + 1;
}</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns cljs-example.core
(:require [lib.inc :as lib]))
(lib/<span class="code-keyword">default</span> 0)</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">goog.provide(<span class="code-quote">"module$lib$inc"</span>);
function inc$$module$lib$inc(v){<span class="code-keyword">return</span> v+1}
module$lib$inc.<span class="code-keyword">default</span>=inc$$module$lib$inc</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-comment">// Compiled by ClojureScript 1.8.40 {}
</span>goog.provide('cljs_example.core');
goog.require('cljs.core');
goog.require('module$lib$inc');
module$lib$inc.<span class="code-keyword">default</span>$.call(<span class="code-keyword">null</span>,(0));
<span class="code-comment">//# sourceMappingURL=core.js.map</span></pre>
</div></div>CLJS-1620In JavaScript ES2015 modules default export name is munged to default$DefectMinorOpenUnresolvedUnassignedRoman LiutikovFri, 8 Apr 2016 13:50:22 -0500Fri, 8 Apr 2016 14:42:32 -050001<p>One possible path around this is to respect the Closure Compiler language setting when munging instead of blindly munging ECMA-262 keywords. A patch that adopts this approach would be welcome.</p>Global Rank[CLJS-1618] `extend-type string` doesnt work without wrapping the string object into `(str)`http://dev.clojure.org/jira/browse/CLJS-1618
ClojureScript<p>(ns my.car)</p>
<p>(defprotocol Car<br/>
(drive <span class="error">&#91;this&#93;</span>))</p>
<p>(extend-type js/String<br/>
Car<br/>
(drive <span class="error">&#91;this&#93;</span> (map #({"a" "A"} %) <span class="error">&#91;this (str this)&#93;</span>)))</p>
<p>(drive "a"); (nil "A") expected ("A" "A")</p>
<p>See the reproduction of the bug in a live environment with KLISPE here: <a href="http://app.klipse.tech/?sourcce=jira&amp;cljs_in=(ns%20my.car)%0A%0A(defprotocol%20Car%0A%20%20(drive%20%5Bthis%5D))%0A%0A(extend-type%20js%2FString%0A%20%20Car%0A%20%20(drive%20%5Bthis%5D%20(map%20%23(%7B%22a%22%20%22A%22%7D%20%25)%20%5Bthis%20(str%20this)%5D)))%0A%0A%0A(drive%20%22a%22)%0A">http://app.klipse.tech/?sourcce=jira&amp;cljs_in=(ns%20my.car)%0A%0A(defprotocol%20Car%0A%20%20(drive%20%5Bthis%5D))%0A%0A(extend-type%20js%2FString%0A%20%20Car%0A%20%20(drive%20%5Bthis%5D%20(map%20%23(%7B%22a%22%20%22A%22%7D%20%25)%20%5Bthis%20(str%20this)%5D)))%0A%0A%0A(drive%20%22a%22)%0A</a></p>CLJS-1618`extend-type string` doesnt work without wrapping the string object into `(str)`DefectMinorOpenUnresolvedUnassignedYehonathan SharvitThu, 7 Apr 2016 17:36:12 -0500Sun, 10 Apr 2016 00:24:18 -05001.7.22800<p>This is because of boxing and the implementation of cljs.core.&#95;EQ&#95;</p>
<p>By extending type js/String (the String object/class in javascript) instead of "string", your "this" will be the boxed string rather than the primitive string (in non-strict js mode--in strict mode it will be the primitive also). The (str this) is coercing the boxed string back to a primitive string.</p>
<p>The core issue is really:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(= (js/<span class="code-object">String</span>. <span class="code-quote">"a"</span>) <span class="code-quote">"a"</span>) ;=&gt; <span class="code-keyword">false</span>
;; thus
({<span class="code-quote">"a"</span> <span class="code-quote">"A"</span>} (js/<span class="code-object">String</span>. <span class="code-quote">"a"</span>)) ;=&gt; nil</pre>
</div></div>
<p>You should really use</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(extend-type string ...)</pre>
</div></div><p>BTW this appears to be different from Clojure where primitives and boxed-primitives appear equal:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;; Clojure code
(= (<span class="code-object">String</span>. <span class="code-quote">"a"</span>) <span class="code-quote">"a"</span>)
=&gt; <span class="code-keyword">true</span>
(= (<span class="code-object">Long</span>. 1) 1)
=&gt; <span class="code-keyword">true</span>
(= (<span class="code-object">Long</span>. 1) (<span class="code-object">long</span> 1))
=&gt; <span class="code-keyword">true</span></pre>
</div></div>
<p>Not sure if clojurescript should try to replicate this more closely or not.</p>
<p>Clojurescript bottoms out with triple-equals in most cases, which is why primitives and boxes do not compare equal. To get them to compare equal would require adding special (instance? js/BOXED x) checks and some modifications to existing -equiv implementations which extend primitive types. (e.g. (extend-type number IEquiv ...) uses identical? without checking if the right-hand side is boxed or not.)</p><p>As Francis alludes to, this is not a bug. If you do <tt>(doc extend-type)</tt>, it indicates the <tt>type-sym</tt> can be <tt>string</tt> to cover the base type <tt>js/String</tt>, and it elaborates with <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Note that, <span class="code-keyword">for</span> example, string should be used instead of js/<span class="code-object">String</span>.</pre>
</div></div> and if a user does try to use <tt>js/String</tt> as the <tt>type-sym</tt> argument, a diagnostic is issued:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">WARNING: Extending an existing JavaScript type - use a different symbol name instead of js/<span class="code-object">String</span> e.g string at line 1</pre>
</div></div> Global Rank[CLJS-1625] Clojurescript macros used in named function are expanded two times because the analyzer performs a two pass analysis when analyzing named functionshttp://dev.clojure.org/jira/browse/CLJS-1625
ClojureScriptCLJS-1625Clojurescript macros used in named function are expanded two times because the analyzer performs a two pass analysis when analyzing named functionsDefectMinorOpenUnresolvedUnassignedEwen GrosjeanSat, 16 Apr 2016 09:32:16 -0500Tue, 19 Apr 2016 14:07:31 -050000<p>During the first analysis of named functions, only the function definition is analyzed in order to know its function-ness/arity. Its body is only analyzed during the second pass.</p><p><a href="http://dev.clojure.org/jira/browse/CLJS-1617">http://dev.clojure.org/jira/browse/CLJS-1617</a> seems to add a similar issue</p>Global Rank[CLJS-1639] Invalid file path for cljs.core.load_file on windowshttp://dev.clojure.org/jira/browse/CLJS-1639
ClojureScript<p>When I tried to build reagent based app with nodejs target, <br/>
I got an invalid file path generated case which is basically loading external javascript file.<br/>
I captured the image as following:</p>
<p><img src="https://dl.dropboxusercontent.com/u/254812/cljs/invalid_path_cljs_core_load_file.jpg" align="absmiddle" border="0" /></p>
<p>At line 4, the path should have double backward-slash on windows.</p>
<p>I has built a CLJS app which is based on reagent framework with nodejs target. The build environment is somewhat strange but I have a case to use it. Here is a reproduce steps.</p>
<ol>
<li>Open command prompt on windows 10 and execute command as following:<br/>
<tt>lein new figwheel sample00 &#8211; --reagent</tt></li>
<li>Open project.clj file and update one of dependencies:
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>project.clj</b></div><div class="codeContent panelContent">
<pre class="code-java">;; ...
:dependencies [[org.clojure/clojure <span class="code-quote">"1.8.0"</span>]
[org.clojure/clojurescript <span class="code-quote">"1.8.51"</span>]
[org.clojure/core.async <span class="code-quote">"0.2.374"</span>
:exclusions [org.clojure/tools.reader]]
[reagent <span class="code-quote">"0.6.0-alpha"</span> :exclusions [cljsjs/react]]
[cljsjs/react-with-addons <span class="code-quote">"0.14.3-0"</span>]
]
;; ...
:cljsbuild {:builds [{:id <span class="code-quote">"dev"</span>
;; ...
:compiler {
;; ...
:target :nodejs
}
}]
}
;; ...</pre>
</div></div></li>
<li>Build with <tt>lein cljsbuild once dev</tt></li>
<li>Open <tt>&lt;project_root&gt;\resources\public\js\compiled\out\reagent\impl\util.js</tt></li>
<li>At line number 4 in my environment, the generated code is<br/>
<tt>cljs.core.load_file("resources\public\js\compiled\out\react-with-addons.inc.js");</tt><br/>
However I believe the correct path string should be <tt>cljs.core.load_file("resources\\public\\js\\compiled\\out<br clear="all" />react-with-addons.inc.js");</tt>.</li>
</ol>
<p>Backward-slash needs to be double on Windows env. <br/>
When I lunched doo test command with nodejs target, it complained about the given path cannot be loaded.</p>
<p>Thanks.</p>
Windows 10, CLJS 1.8.51CLJS-1639Invalid file path for cljs.core.load_file on windowsDefectMinorOpenUnresolvedUnassignedJay LeebugFri, 13 May 2016 19:48:38 -0500Sat, 21 May 2016 17:07:09 -05001.7.22800<p>This ticket is in danger of being closed. The ticket should demonstrate a reproducible bug without relying on any 3rd party tools or libraries. No Leiningen, Figwheel, or Reagent. Please demonstrate the Windows issue with only ClojureScript.</p>
<p>Thanks.</p>Global Rank[CLJS-1644] Recursive protocol method for a record never terminateshttp://dev.clojure.org/jira/browse/CLJS-1644
ClojureScript<p>When extending a protocol for a record, a recursive method can never terminate in some cases.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defrecord R [a])
(defprotocol P
(f [x]))
(extend-protocol P
R
(f [x]
(<span class="code-keyword">if</span> x
(recur nil)
x))
<span class="code-keyword">default</span>
(f [x]
(<span class="code-keyword">if</span> x
(recur nil)
x)))
(prn (f 1)) ; #1
(prn (f (R. 1))) ; #2</pre>
</div></div>
<p><tt>prn</tt> call #1 prints <tt>nil</tt> as expected, but <tt>prn</tt> call #2 never terminates.</p>
<p>It looks like the compiler creates a variable assigned to <tt>this</tt> within the <tt>while</tt> loop such that the test of "<tt>x</tt>" is always really testing <tt>this</tt> when it should be testing the value of <tt>x</tt> passed in by the call to <tt>recur</tt>.</p>
<p>Note, I'm testing ClojureScript 1.8.51. The "Affects Version/s" field above only gives 1.7.228 as the most recent version.</p>AnyCLJS-1644Recursive protocol method for a record never terminatesDefectMinorOpenUnresolvedUnassignedBrian StilesMon, 23 May 2016 04:05:33 -0500Thu, 26 May 2016 15:16:21 -05001.7.22800<p>Actually, "always really testing 'this' when it should be testing the value of x passed in by the call to recur" is only true if the type of the value represented by x remains the same. If, as in the example, the type changes, the call should be dispatched to the properly matching method implementation.</p>
<p>This seems to behave as expected in Clojure.</p>Global Rank[CLJS-1678] variadic defn can be called for missing fixed arities, overlapping arityhttp://dev.clojure.org/jira/browse/CLJS-1678
ClojureScript<p>For defns with a variadic arity: if invoked with a missing fixed arity, they use the variadic method instead of erroring; if invoked with a fixed arity that is the max fixed arity, variadic mathod instead of fixed form is invoked.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn f-hole
([a] 1)
([a b c d &amp; args] <span class="code-quote">"4 or more"</span>))
(f-hole 1 2) ; =&gt;<span class="code-quote">"4 or more"</span>, should be error
(defn f-overlap-mfa
([a b] 2)
([a b &amp; c] <span class="code-quote">"2+"</span>))
(f-overlap-mfa 1) ;=&gt; <span class="code-quote">"2+"</span>, should be error
(f-overlap-mfa 1 2) ;=&gt; <span class="code-quote">"2+"</span>, should be 2
(f-overlap-mfa 1 2 3) ;=&gt; <span class="code-quote">"2+"</span>, correct</pre>
</div></div>
<p>A way to fix the f-hole bug is to emit a "case X:" into the switch statement for all X with no signature or less than max-fixed-arity.</p>
<p>The f-overlap-mfa I'm not sure why is happening and didn't investigate deeply.</p>CLJS-1678variadic defn can be called for missing fixed arities, overlapping arityDefectMinorReopenedUnresolvedUnassignedFrancis AvilaSat, 11 Jun 2016 08:30:21 -0500Sun, 12 Jun 2016 09:41:18 -050000<p>Sorry, filed against CLJ instead of CLJS!</p><p>The behaviour I am seeing for <tt>f-overlap-mfa</tt> is:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(f-overlap-mfa 1) ;=&gt; <span class="code-quote">"2+"</span>
(f-overlap-mfa 1 2) ;=&gt; 2
(f-overlap-mfa 1 2 3) ;=&gt; <span class="code-quote">"2+"</span></pre>
</div></div>
<p>So the two argument result is different for me than you, <span class="nobr"><a href="http://dev.clojure.org/jira/secure/ViewProfile.jspa?name=favila" class="user-hover" rel="favila"><sup><img class="rendericon" src="http://dev.clojure.org/jira/images/icons/user_12.gif" height="12" width="12" align="absmiddle" alt="" border="0"/></sup>Francis Avila</a></span>.</p>
<p>The call with just one argument does give a warning though:</p>
<p><tt>WARNING: Wrong number of args (1) passed to cljs.user/f-overlap-mfa</tt></p>Global Rank[CLJS-1076] :nashorn targethttp://dev.clojure.org/jira/browse/CLJS-1076
ClojureScript<p>To run well on Nashorn the target should supply <tt>CLOSURE_IMPORT_SCRIPT</tt> as well as <tt>setTimeout</tt> or <tt>setImmediate</tt> for core.async.</p>CLJS-1076:nashorn targetEnhancementMinorOpenUnresolvedUnassignedDavid NolenMon, 2 Mar 2015 16:26:01 -0600Mon, 2 Mar 2015 16:26:01 -060010Global Rank[CLJS-1712] Make PersistentHashSet implement IReducehttp://dev.clojure.org/jira/browse/CLJS-1712
ClojureScript<p>This improves speed of many reduce based operations on set which were falling back to seq-reduce, including code in `clojure.set` namespace such as `clojure.set/union` and `(into [] some-set)`.</p>
<p>I've included a few benchmarks I performed using `simple-benchmark` in a JavascriptCore environment (Planck REPL)</p>CLJS-1712Make PersistentHashSet implement IReduceEnhancementMinorOpenUnresolvedUnassignedThomas MulvaneyperformanceThu, 21 Jul 2016 07:34:34 -0500Thu, 21 Jul 2016 15:35:31 -050000<p>I think the code currently is faithful to Clojure's implementation of PersistentHashSet. So any change from that would probably require more thought and/or history.</p>
<p>Also someone else also raised a similar issue on <a href="https://groups.google.com/forum/#!topic/clojurescript/h-EYTTndvAY">ClojureScript mailing list</a>.</p>Global RankPatchCode[CLJS-1709] clojure.data/diff throws an exception when comparing map keys of different types when used on sorted mapshttp://dev.clojure.org/jira/browse/CLJS-1709
ClojureScript<p>e.g.<br/>
(clojure.data/diff (sorted-map :foo 42) (sorted-map 1 42))<br/>
(clojure.data/diff (sorted-map :foo 42) (sorted-map "x" 42))<br/>
(clojure.data/diff (hash-map :foo 42) (sorted-map 1 42))<br/>
(clojure.data/diff (hash-map :foo 42) (sorted-map "x" 42))<br/>
will throw e.g.<br/>
Error: Cannot compare :foo to 1<br/>
while e.g.<br/>
(clojure.data/diff (hash-map :foo 42) (hash-map 1 42))<br/>
(clojure.data/diff (hash-map :foo 42) (hash-map "x" 2))<br/>
(clojure.data/diff (sorted-map :foo 42) (sorted-map :bar 42))<br/>
will not.</p>
<p>The same applies to Clojure with a different exception (e.g. "java.lang.Long cannot be cast to clojure.lang.Keyword")</p>CLJS-1709clojure.data/diff throws an exception when comparing map keys of different types when used on sorted mapsDefectMinorOpenUnresolvedUnassignedThomas ScheiblauerbugTue, 19 Jul 2016 05:07:33 -0500Fri, 22 Jul 2016 07:34:41 -05001.9.7601Global Rank[CLJS-746] clojure.string/replace pattern/function of match API difference with clojure versionhttp://dev.clojure.org/jira/browse/CLJS-746
ClojureScript<p>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. </p>
<p>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.</p>[org.clojure/clojurescript &quot;0.0-2138&quot;]CLJS-746clojure.string/replace pattern/function of match API difference with clojure versionDefectMinorOpenUnresolvedUnassignedCurtis GagliardiFri, 10 Jan 2014 01:22:28 -0600Fri, 10 Jan 2014 01:32:48 -060002<p>Afraid I don't see how to edit, but I wanted to include a simple example:</p>
<p>CLJS: <br/>
(clojure.string/replace "hello world" #"(hello) world" (fn <span class="error">&#91;m&#93;</span> (.log js/console (str "Match: " m)) m))</p>
<p>will log: "Match: hello world"</p>
<p>CLJ<br/>
user=&gt; (clojure.string/replace "hello world" #"(hello) world" (fn <span class="error">&#91;m&#93;</span> (println (str "Match: " m) m)))<br/>
Match: <span class="error">&#91;&quot;hello world&quot; &quot;hello&quot;&#93;</span> <span class="error">&#91;hello world hello&#93;</span></p>
<p>NullPointerException java.util.regex.Matcher.quoteReplacement (Matcher.java:655)</p>Global Rank[CLJS-1109] Record type name and advanced optimizationhttp://dev.clojure.org/jira/browse/CLJS-1109
ClojureScript<p>It is not possible to query type name in advanced compilation. <br/>
Code below prints correct record name in other compilation modes, but under advanced compilation it prints constructor source code.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defrecord FooBar [a])
(def fb (FooBar. 1))
(prn (-&gt; fb))
(prn (-&gt; fb type))
(prn (-&gt; fb type pr-str))</pre>
</div></div>CLJS-1109Record type name and advanced optimizationDefectMinorOpenUnresolvedUnassignedDaniel SkardaThu, 12 Mar 2015 09:00:53 -0500Thu, 12 Mar 2015 09:00:53 -05000.0-305801Global Rank[CLJS-677] cljs.reader doesn't support keywords starting with a digithttp://dev.clojure.org/jira/browse/CLJS-677
ClojureScript<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:foo&gt; (r/read-string <span class="code-quote">":0"</span>)
<span class="code-quote">"Error evaluating:"</span> (r/read-string <span class="code-quote">":0"</span>) :as <span class="code-quote">"cljs.reader.read_string.call(<span class="code-keyword">null</span>,\"</span>:0\<span class="code-quote">")"</span>
org.mozilla.javascript.EcmaError: TypeError: Cannot read property <span class="code-quote">"0.0"</span> from <span class="code-keyword">null</span> (file:/home/chas/dev/clojure/cljs/.repl/cljs/reader.js#451)</pre>
</div></div>
<p>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 <a href="http://dev.clojure.org/jira/browse/CLJ-1286" title="Fix reader spec and regex to match code for keywords starting with digits">CLJ-1286</a>.</p>
<p>BTW, this is another <a href="https://github.com/reiddraper/simple-check/">simple-check</a> win... <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/></p>CLJS-677cljs.reader doesn't support keywords starting with a digitDefectMinorOpenUnresolvedUnassignedChas EmerickTue, 12 Nov 2013 10:37:35 -0600Thu, 10 Sep 2015 09:35:11 -050046<p>This is not a simple regex change, as I had hoped given the recent flurry in Clojure. The symbol pattern in <tt>cljs.reader</tt> 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 <tt>clojure.tools.reader.impl.commons/parse-symbol</tt> (which incidentally doesn't use a regex)…either way, leaving it for another day (or someone else, if they're up for it).</p><p>I think I fixed the match processing issue you're talking about (<a href="http://dev.clojure.org/jira/browse/CLJS-775" title="cljs.reader parses radix form of int literals (e.g. 2r101) incorrectly "><del>CLJS-775</del></a> <a href="http://dev.clojure.org/jira/browse/CLJS-776" title="re-matches is incorrect">CLJS-776</a>)? However I'm still confused by this and <a href="http://dev.clojure.org/jira/browse/CLJ-1286" title="Fix reader spec and regex to match code for keywords starting with digits">CLJ-1286</a>. 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?</p><p>AFAIK EDN specs do not reject :0 (no rule that the second character cannot be a digit). See <a href="https://github.com/wagjo/serialization-formats">https://github.com/wagjo/serialization-formats</a> for my interpretation of existing specs.</p><p>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</p>
<ol>
<li>First character is a colon, then the second character and after are matched against the symbol definition.</li>
<li>The first character is a colon, and the whole form is matched against the symbol definition.</li>
</ol>
<p><a href="http://dev.clojure.org/jira/browse/CLJ-1003" title=":100 is a valid Clojure keyword. Is that intentional?"><del>CLJ-1003</del></a> <a href="http://dev.clojure.org/jira/browse/CLJ-1252" title="Clojure reader (incorrectly) accepts keywords starting with a number "><del>CLJ-1252</del></a> and <a href="http://dev.clojure.org/jira/browse/CLJ-1286" title="Fix reader spec and regex to match code for keywords starting with digits">CLJ-1286</a> 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).</p>
<p>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 <a href="http://dev.clojure.org/jira/browse/CLJ-1252" title="Clojure reader (incorrectly) accepts keywords starting with a number "><del>CLJ-1252</del></a> was accepted by Alex Miller erroneously.</p>
<p>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.)</p>
<p>Also EDN allows contiguous colons in symbols, whereas clojure 1.6 and the reader spec do not.</p><p>Also clojure 1.6 allows <tt>a/:a</tt> and <tt>:a/:a</tt> (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...)</p><p>I think this pattern follows the specs:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">#"(?x)
(?!<span class="code-comment">///) # edge <span class="code-keyword">case</span>: / only allowed in name part.
</span># name or namespace part of symbol or keyword
(?:
#division symbol
(/
# normal symbol
|[a-zA-Z*!_?$%&amp;=&lt;&gt;][0-9a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-]*
# symbol starting with [-+.]
|[-+.](?:[a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-][0-9a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-]*)?)
# keyword
|(::?)([0-9a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-]+))
# name part when namespace is present
(?:/(/ # division symbol
|[a-zA-Z*!_?$%&amp;=&lt;&gt;][0-9a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-]*
|[-+.](?:[a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-][0-9a-zA-Z*!_?$%&amp;=&lt;&gt;\#:+.-]*)?))?
# 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)"</pre>
</div></div>
<p>Problems:</p>
<ol>
<li>Does not enforce no-repeating-colon rule (but it is easy to validate after matching).</li>
<li>Rejects violations of first-character-rule in symbols which clojure accepts.</li>
<li>Accepts a trailing colon on namespace (unlike clojure).</li>
<li>Accepts <tt>foo//</tt> or <tt>:foo//</tt>, 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.</li>
</ol>
<p>Another problem: Accepts <tt>:::a/b</tt>, which I think is ok per the specs but is not read by 1.6. Crazy example:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">user=&gt; (require ['clojure.core :as (symbol <span class="code-quote">":a"</span>)])
nil
user=&gt; :::a/map
RuntimeException Invalid token: :::a/map clojure.lang.Util.runtimeException (Util.java:221)
user=&gt; (resolve (symbol <span class="code-quote">":a"</span> <span class="code-quote">"map"</span>))
#'clojure.core/map</pre>
</div></div>
<p>Theoretically I might expect <tt>:::a/map</tt> to be read as <tt>:clojure.core/map</tt>?</p><p>Bumping this up, as I just scratched my head for an hour to find out this was the culprit</p><p>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.</p><p>I think <a href="http://dev.clojure.org/jira/browse/CLJ-1527" title="Clarify and align valid symbol and keyword rules for Clojure (and edn)">CLJ-1527</a> is currently the ticket where this problem is pursued.</p>Global Rank[CLJS-1726] demunge is too agreesive and incorrect in some caseshttp://dev.clojure.org/jira/browse/CLJS-1726
ClojureScript<p>I have implemented some "demunging" logic in cljs-devtools (and dirac) to present original user-friendly names in UI.</p>
<p>During my testing I spotted some wrong edge-cases and incorrect behaviours of demunge:</p>
<p>1) it is too aggressive in replacing dollars - some dollars can be "real" dollars as part of original name<br/>
2) it does not revert js-reserved? transformation applied during munging<br/>
3) it is oblivious to underscores/dashes - some underscores were "real" underscores before munging<br/>
(this may be not complete)</p>
<p>I have worked around those issues on my side and implemented some heuristics<span class="error">&#91;1&#93;</span> based on context, but it is far from perfect.</p>
<p>I'm not sure how to properly fix those, so I wanted to open a ticket with discussion. Maybe people will have some clever ideas.</p>
<p>Currently munging is lossy and we probably don't want to touch it for compatibility reasons. <br/>
Maybe we could mark original underscores and dollars in some way, so demunge could properly skip them.</p>
<p>1) One strategy could be to use some (rare) unicode characters, but that would be problematic for people to type.<br/>
2) Another strategy could be to escape original dollars and underscores somehow (using more dollars and underscores <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/wink.gif" height="20" width="20" align="absmiddle" alt="" border="0"/>.<br/>
3) Better ideas?</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://github.com/binaryage/cljs-devtools/blob/52899e61e33373df36be8dcb23c69377936821b2/src/lib/devtools/munging.cljs#L154-L185">https://github.com/binaryage/cljs-devtools/blob/52899e61e33373df36be8dcb23c69377936821b2/src/lib/devtools/munging.cljs#L154-L185</a></p>CLJS-1726demunge is too agreesive and incorrect in some casesEnhancementMinorOpenUnresolvedUnassignedAntonin HildebrandThu, 4 Aug 2016 16:23:28 -0500Thu, 4 Aug 2016 16:23:28 -050000Global Rank[CLJS-1722] Upgrade ExceptionInfo to proper deftypehttp://dev.clojure.org/jira/browse/CLJS-1722
ClojureScript<p>Currently ExceptionInfo is implemented as a raw constructor function which inherits from js/Error with some ad-hoc javascript-level patches to satisfy a tiny subset of deftype functionality (mainly for printing).</p>
<p>Unfortunately this does not play well with cljs-devtools<span class="error">&#91;1&#93;</span>. This problem surfaced when I started playing with ExceptionInfo and cljs-devtools v0.8 which newly supports printing deftypes<span class="error">&#91;2&#93;</span>. ExceptionInfo does not contain getBasis, cljs$lang$type, cljs$lang$ctorStr and similar machinery.</p>
<p>My proposed patch implements ExceptionInfo as a proper deftype and does some patch-work to provide backward compatibility. I'm pretty sure we must not break current contract of ExceptionInfo constructor accepting 3 args and synthesizing other fields on the fly in constructor.</p>
<p>Implementation details:<br/>
1) first we define ExceptionInfo as normal deftype (to get a template)<br/>
2) then we remember reference to ExceptionInfo in ExceptionInfoTypeTemplate<br/>
3) then we redefine ExceptionInfo with raw constructor function which should mimic original behaviour (by scraping newly created js/Error instance, but calling ExceptionInfoTypeTemplate to do proper deftype initialization)<br/>
4) then we copy keys from ExceptionInfoTypeTemplate over ExceptionInfo<br/>
5) then we set ExceptionInfo's prototype to be ExceptionInfoTypeTemplate's prototype<br/>
6) then we fix ExceptionInfo's prototype's constructor to point to our re-defined constructor function<br/>
7) then we patch ExceptionInfo's prototype to inherit from js/Error (note this clobbers ExceptionInfoTypeTemplate as well - but we don't care about it)</p>
<p>This effectively gives us properly working ExceptionInfo deftype with redefined constructor function wrapping deftype's constructor for backwards compatibility. <br/>
We also patch ExceptionInfo's prototype to inherit from js/Error the same was as original code did.</p>
<p>Note: With working deftype, we can move IPrintWithWriter and toString implementation to the deftype itself.</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://github.com/binaryage/cljs-devtools/issues/23">https://github.com/binaryage/cljs-devtools/issues/23</a><br/>
<span class="error">&#91;2&#93;</span> <a href="https://github.com/binaryage/cljs-devtools/releases/tag/v0.8.0">https://github.com/binaryage/cljs-devtools/releases/tag/v0.8.0</a></p>CLJS-1722Upgrade ExceptionInfo to proper deftypeEnhancementMinorOpenUnresolvedUnassignedAntonin HildebrandWed, 3 Aug 2016 17:54:52 -0500Thu, 4 Aug 2016 13:25:16 -050001<p>Why not just add the missing <tt>getBasis</tt>, <tt>cljs$lang$type</tt>, <tt>cljs$lang$ctorStr</tt> bits per <tt>set!</tt>?</p>
<p>The patch looks like it would mess up advanced compilation although that is just an instinct not something I verified, did you?</p><p>I ran clojurescript tests and I assumed they run also against advanced-mode build. During development when my tests were failing I saw error messages about minified names.</p>
<p>This may seem as a hacky solution, but IMO the original code was also a hack. My hack will stay up-to-date with future changes to deftype implementation. I can imagine people would forget to update this part when touching deftype. </p>
<p>btw. there is another patch coming related to discrepancies between deftype and defrecord. That could have been avoided if defrecord shared common implementation with deftype.</p><p>Closure is usually very strict about re-defining stuff but I guess my instincts were wrong, the tests should cover advanced.</p>
<p>My issue with this is that <tt>deftype</tt> is for defining Clojure-specific types. ExceptionInfo is not since it inherits from Error, just like you can't have a superclass in Clojure you can't in CLJS. So IF we were to change <tt>deftype</tt> in the future we might break things in unexpected ways that just re-use <tt>deftype</tt> but aren't actually <tt>deftype</tt>.</p>
<p>Yes, you have to do some house-keeping but you can't enforce the rules of <tt>deftype</tt> when dealing with inheritance.</p>
<p>Just my 2 cents, it has advantages to re-use <tt>deftype</tt> too (as you suggested).</p><p>Unfortunately I was unable to look up any comments or docs explaining the reasoning why we do that js/Error inheritance there. </p>
<p>My first attempt to "fix" ExceptionInfo was to simply implement it as an ordinary deftype. And that worked just fine (for my tests). Then I tried to re-implement original behaviours on top just to make it 100% compatible.</p><p>Just adding a motivational screenshot:</p>
<p><a href="https://dl.dropboxusercontent.com/u/559047/CLJS-1722-example.png">https://dl.dropboxusercontent.com/u/559047/CLJS-1722-example.png</a></p>
<p>Those yellow warnings are listing which properties are getting copied by gobject/extend call. <br/>
The expanded log item is new implementation logged via cljs-devtools v0.8.0.<br/>
The last log item is the old implementation logged via cljs-devtools v0.8.0 (cljs-devtools does not recognise ExceptionInfo as CLJS type, but detects IPrintWithWriter and uses it to present the value)</p>Global RankPatchCode[CLJS-1755] Support sourcesContent in source mapshttp://dev.clojure.org/jira/browse/CLJS-1755
ClojureScript<p>This issue adds sourcesContent support for source maps: <a href="https://github.com/google/closure-compiler/issues/1890">https://github.com/google/closure-compiler/issues/1890</a>. This means that your source maps can include your source as well in one bundled file. This makes handling sourcemaps much easier for things like error tracking services. It could also simplify config for source mapping as everything is included in the source map and you don't need to specify relative paths, e.t.c.</p>
<p>This will need to wait for the next release of the Closure Compiler.</p>CLJS-1755Support sourcesContent in source mapsEnhancementMinorOpenUnresolvedUnassignedDaniel ComptonsourcemapTue, 16 Aug 2016 21:16:00 -0500Tue, 16 Aug 2016 21:16:00 -050001Global Rank[CLJS-1766] Set literals in REPL end up reified as ArrayMap backed PersistentHashSets.http://dev.clojure.org/jira/browse/CLJS-1766
ClojureScript<p>Entering a set literal in the REPL with more than 8 elements should create a PHM backed set but instead it is array backed.</p>
<p>Example (in REPL):<br/>
cljs.user=&gt; (type (.-hash-map #{1 2 3 4 5 6 7 8 9}))<br/>
cljs.core/PersistentArrayMap</p>
<p>This means operations such as `get` and `contains?` end up doing long scans and are slower than a user would expect.</p>CLJS-1766Set literals in REPL end up reified as ArrayMap backed PersistentHashSets.DefectMinorOpenUnresolvedUnassignedThomas MulvaneyreplSun, 28 Aug 2016 06:35:33 -0500Sun, 28 Aug 2016 06:35:33 -050001Global Rank[CLJS-1776] Add fixed arities for mapcathttp://dev.clojure.org/jira/browse/CLJS-1776
ClojureScript<p>Following the pattern of map, this patch adds three fixed arities for mapcat.</p>CLJS-1776Add fixed arities for mapcatEnhancementMinorOpenUnresolvedUnassignedRobert C FaberperformanceTue, 13 Sep 2016 08:44:50 -0500Tue, 13 Sep 2016 10:25:03 -05001.9.7601<p>Presumably this is to improve performance. Please include a benchmark showing the difference.</p>Global RankPatchCode[CLJS-1048] support function values in static vars compile time metadatahttp://dev.clojure.org/jira/browse/CLJS-1048
ClojureScript<p>Function values are currently only supported for :test metadata key as a special case. </p>CLJS-1048support function values in static vars compile time metadataEnhancementMinorOpenUnresolvedUnassignedIvan MikushinFri, 20 Feb 2015 06:05:50 -0600Fri, 20 Feb 2015 06:05:50 -060002Global Rank[CLJS-1783] Unify List creation codehttp://dev.clojure.org/jira/browse/CLJS-1783
ClojureScript<p>There is some duplication and redundant functions around List creation.</p>
<p>In this patch a fromArray method was added to List, consistent with other persistent data structures in the code base.</p>CLJS-1783Unify List creation codeEnhancementMinorOpenUnresolvedUnassignedThomas MulvaneyTue, 20 Sep 2016 20:26:09 -0500Tue, 20 Sep 2016 20:27:03 -050000Global RankPatchCode[CLJS-1685] Incorrectly lazy subvec when start param is nilhttp://dev.clojure.org/jira/browse/CLJS-1685
ClojureScript<p>subvec in ClojureScript does not fail when start param is nil. This is different than in regular Clojure.</p>
<p>In Clojure:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def foo (subvec nil 1))
CompilerException java.lang.IndexOutOfBoundsException, compiling:(form-init4645269128697935824.clj:1:10)
(def foo (subvec nil nil))
CompilerException java.lang.NullPointerException, compiling:(form-init4645269128697935824.clj:1:10)</pre>
</div></div>
<p>In ClojureScript:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def foo (subvec nil 1))
#object[Error Error: Index out of bounds]
cljs.core/build-subvec (jar:file:/Users/stoyle/.m2/repository/org/clojure/clojurescript/1.9.36/clojurescript-1.9.36.jar!/cljs/core.cljs:5316:16)
Function.cljs.core.subvec.cljs$core$IFn$_invoke$arity$3 (jar:file:/Users/stoyle/.m2/repository/org/clojure/clojurescript/1.9.36/clojurescript-1.9.36.jar!/cljs/core.cljs:5328:7)
Function.cljs.core.subvec.cljs$core$IFn$_invoke$arity$2 (jar:file:/Users/stoyle/.m2/repository/org/clojure/clojurescript/1.9.36/clojurescript-1.9.36.jar!/cljs/core.cljs:5326:7)
cljs$core$subvec (jar:file:/Users/stoyle/.m2/repository/org/clojure/clojurescript/1.9.36/clojurescript-1.9.36.jar!/cljs/core.cljs:5319:1)
=&gt; nil
(def foo (subvec nil nil))
=&gt; #'user/foo</pre>
</div></div>
<p>foo is of course not usable after this:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">foo
#object[Error Error: No protocol method IIndexed.-nth defined <span class="code-keyword">for</span> type <span class="code-keyword">null</span>: ]
cljs.core/missing-protocol (jar:file:/Users/stoyle/.m2/repository/org/clojure/clojurescript/1.9.36/clojurescript-1.9.36.jar!/cljs/core.cljs:264:4)</pre>
</div></div>ClojureScript 1.9.36 on Mac and WindowsCLJS-1685Incorrectly lazy subvec when start param is nilDefectMinorOpenUnresolvedUnassignedAlf Kristian StøyleFri, 17 Jun 2016 08:41:01 -0500Mon, 26 Sep 2016 13:37:31 -05001.9.3601<p>Added fix and test.</p>Global Rank[CLJS-1784] Cleanup set creation functionshttp://dev.clojure.org/jira/browse/CLJS-1784
ClojureScript<p>Use .fromArray for consistency/speed when handling zeroed IndexedSeqs.</p>
<p>Use reduce as the default construction path to take advantage of reducible collections.</p>CLJS-1784Cleanup set creation functionsEnhancementMinorOpenUnresolvedUnassignedThomas MulvaneyTue, 20 Sep 2016 22:05:45 -0500Wed, 28 Sep 2016 01:30:26 -050000<p><span class="nobr"><a href="http://dev.clojure.org/jira/secure/ViewProfile.jspa?name=tmulvaney" class="user-hover" rel="tmulvaney"><sup><img class="rendericon" src="http://dev.clojure.org/jira/images/icons/user_12.gif" height="12" width="12" align="absmiddle" alt="" border="0"/></sup>Thomas Mulvaney</a></span>, could you provide some benchmarks for the speed assertion? It would be nice to run it on Chrome/Firefox/Safari.</p><p>Sure thing, I'll do some more benchmarks.</p>Global RankPatchCode[CLJS-1792] Can't load clojure.spec.test when clojure.test.check is unavailablehttp://dev.clojure.org/jira/browse/CLJS-1792
ClojureScript<p>Requiring clojure.spec.test results in an error, because it's looking for clojure.test.spec.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns foo.bar
(:require [clojure.spec.test]))</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Caused by: clojure.lang.ExceptionInfo: No such namespace: clojure.test.check, could not locate clojure/test/check.cljs, clojure/test/check.cljc, or Closure namespace <span class="code-quote">"clojure.test.check"</span> in file file:/home/arne/.m2/repository/org/clojure/clojurescript/1.9.229/clojurescript-1.9.229.jar!/cljs/spec/test.cljs {:tag :cljs/analysis-error}</pre>
</div></div>
<p>This problem goes away when adding org.clojure/test.check as a dependency. </p>
<p>This is not an issue in Clojure. An exception is only raised when calling a function that relies on test.check.</p>{code:clojure}
<br/>
[org.clojure/clojure &quot;1.9.0-alpha12&quot;]
<br/>
[org.clojure/clojurescript &quot;1.9.229&quot; :scope &quot;provided&quot;]
<br/>
{code}CLJS-1792Can't load clojure.spec.test when clojure.test.check is unavailableDefectMinorReopenedUnresolvedUnassignedArne BrasseurspecFri, 23 Sep 2016 09:48:42 -0500Fri, 30 Sep 2016 11:42:58 -050001<p>This is not a bug per se, we can't do what Clojure does here. How to best handle is something to consider. Present a good idea and submit a patch.</p>Global Rank[CLJS-1631] The str function should handle JavaScript symbolshttp://dev.clojure.org/jira/browse/CLJS-1631
ClojureScript<p>The str function should handle primitive JavaScript symbols produced by Symbol.for. At the moment the str function raises an exception, because it runs into some JavaScript safety checks by using implicit string coersion via (.join #js <span class="error">&#91;x&#93;</span> "").<br/>
More info on the safety check here: <a href="http://www.2ality.com/2014/12/es6-symbols.html">http://www.2ality.com/2014/12/es6-symbols.html</a><br/>
This ticket is also related to:</p>
<ul class="alternate" type="square">
<li><a href="http://dev.clojure.org/jira/browse/CLJS-1628">http://dev.clojure.org/jira/browse/CLJS-1628</a></li>
<li><a href="http://dev.clojure.org/jira/browse/CLJS-890">http://dev.clojure.org/jira/browse/CLJS-890</a></li>
</ul>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def x (.<span class="code-keyword">for</span> js/Symbol <span class="code-quote">"x"</span>))
(str x)
TypeError: Cannot convert a Symbol value to a string
at Array.join (<span class="code-keyword">native</span>)
at Function.cljs.core.str.cljs$core$IFn$_invoke$arity$1 (/home/roman/workspace/clojurescript/.cljs_node_repl/cljs/core.js:9561:12)
at <span class="code-object">Object</span>.cljs$core$str [as str] (/home/roman/workspace/clojurescript/.cljs_node_repl/cljs/core.js:9543:22)
at repl:1:100
at repl:9:3
at repl:14:4
at <span class="code-object">Object</span>.exports.runInThisContext (vm.js:54:17)
at Domain.&lt;anonymous&gt; ([stdin]:41:34)
at Domain.run (domain.js:228:14)
at Socket.&lt;anonymous&gt; ([stdin]:40:25)</pre>
</div></div>
<p>Calling the toString method on a symbol directly works</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(.toString x)
;;=&gt; <span class="code-quote">"Symbol(x)"</span></pre>
</div></div>CLJS-1631The str function should handle JavaScript symbolsEnhancementMinorOpenUnresolvedUnassignedRoman SchererThu, 21 Apr 2016 16:19:36 -0500Thu, 21 Apr 2016 16:19:50 -050002Global Rank[CLJS-1630] Add unit test for static dispatchhttp://dev.clojure.org/jira/browse/CLJS-1630
ClojureScript<p>This unit test is an edge case that illustrates why in the code of `emit :invoke` we must stay with `call` for the high order case where static information is missing .</p>
CLJS-1630Add unit test for static dispatchEnhancementMinorOpenUnresolvedUnassignedYehonathan SharvitThu, 21 Apr 2016 16:15:45 -0500Wed, 10 Aug 2016 22:52:13 -05001.7.22802<p>Could someone take a look at this unit test?</p>Global Rank[CLJS-1562] WARN on hinted fn call type mismatchhttp://dev.clojure.org/jira/browse/CLJS-1562
ClojureScript<p>If a call is made to a function that has hinted arguments (especially {^boolean} and {^number}), with an expression that is known to not be of that type, emit a diagnostic type mismatch warning.</p>
<p>An example that should emit a warning is:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn f [^<span class="code-object">boolean</span> b])
(f 0)</pre>
</div></div> CLJS-1562WARN on hinted fn call type mismatchEnhancementMinorOpenUnresolvedUnassignedMike FikesSat, 6 Feb 2016 16:20:57 -0600Fri, 18 Mar 2016 12:29:34 -05001.7.22801Global Rank[CLJS-981] Better benchmarking infrastructurehttp://dev.clojure.org/jira/browse/CLJS-981
ClojureScript<p>We should use <tt>ProcessBuilder</tt> 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.</p>CLJS-981Better benchmarking infrastructureTaskMinorOpenUnresolvedUnassignedDavid NolennewbieSat, 17 Jan 2015 11:28:11 -0600Fri, 12 Feb 2016 16:44:39 -060001Global Rank[CLJS-1810] Refactoring of find-and-cache-best-methodhttp://dev.clojure.org/jira/browse/CLJS-1810
ClojureScript<p>find-and-cache-best-method was pretty messy and confusing. cache reset is done in -get-method fn itself and it was basically a dead code. find-best-method is the replacement of it and operates with immutable data instead of internal multimethod's mutable state. <br/>
prefers* function didn't mutate the atom too, so now it takes an immutable value. <br/>
dominates is now an internal helper of find-best-method since it is private and not used by anything else. </p>CLJS-1810Refactoring of find-and-cache-best-methodEnhancementMinorOpenUnresolvedUnassignedAndrey ZaytsevWed, 5 Oct 2016 15:56:05 -0500Wed, 5 Oct 2016 15:56:05 -050001Global RankPatchCode[CLJS-1448] lib-rel-path fails on Windows because of File/separator being \\http://dev.clojure.org/jira/browse/CLJS-1448
ClojureScript<p><a href="https://github.com/clojure/clojurescript/blob/cc953d4be7b4a256fd5eae783f9106a2929a4126/src/main/clojure/cljs/closure.clj#L1210">https://github.com/clojure/clojurescript/blob/cc953d4be7b4a256fd5eae783f9106a2929a4126/src/main/clojure/cljs/closure.clj#L1210</a></p>
<p>That code calls replace with \ on windows, who ends up calling (.replaceAll "foo.js" "." "\") and fails with<br/>
IllegalArgumentException character to be escaped is missing java.util.regex.Matcher.appendReplacement (:-1)</p>WindowsCLJS-1448lib-rel-path fails on Windows because of File/separator being \\DefectMinorOpenUnresolvedUnassignedOrlando WilliambugnewbieMon, 14 Sep 2015 13:13:34 -0500Fri, 12 Feb 2016 16:16:30 -06001.7.4804<p>I can't find a way to edit the description, I meant \ followed by \ but somehow it got a line break</p><p>A patch for this is welcome.</p>Global Rank[CLJS-1543] Support Closure libs using goog.modulehttp://dev.clojure.org/jira/browse/CLJS-1543
ClojureScript<p>goog.module is a new way to define Closure namespaces: <a href="https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide">https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide</a></p>
<p>It is used for example in <a href="https://github.com/google/incremental-dom">https://github.com/google/incremental-dom</a></p>
<p>I didn't do full check of how Closure libraries are handled, but one function which is definitely used by <tt>cljs.closure</tt> is <tt>cljs.js-deps/find-classpath-lib</tt> which calls <tt>cljs.js-deps/parse-js-ns</tt> 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 <tt>goog.provide</tt> and <tt>goog.require</tt> calls. Probably Closure Compiler has some built-in functionality to parse files which could be leveraged.</p>
<p>Besides reading module information from files, another question is if using <tt>goog.module</tt> defined namespaces for traditional/legacy namespaces generated by ClojureScript compiler needs something special. When <tt>goog.module</tt> is required, <tt>goog.require</tt> returns the exported object but no global is set. There is however a function to create the globals: <a href="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">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</a></p>
<p>Notes:</p>
<ul class="alternate" type="square">
<li>Can we still assume that goog.requires all occur before first function declaration?
<ul class="alternate" type="square">
<li>Would be fixed by using possible Closure Compiler functionality</li>
<li>Class <tt>com.google.javascript.jscomp.deps.JsFileParser</tt> looks promising</li>
</ul>
</li>
<li>"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)</li>
</ul>
CLJS-1543Support Closure libs using goog.moduleEnhancementMinorOpenUnresolvedUnassignedJuho TeperiTue, 12 Jan 2016 16:24:56 -0600Wed, 13 Jan 2016 07:31:56 -060002Global Rank[CLJS-1677] Requiring [goog] breaks an :advanced build, but the compiler exits successfullyhttp://dev.clojure.org/jira/browse/CLJS-1677
ClojureScript<p>A single file with the following in it is enough to break a build:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns goog-error.core
(:require [goog]))</pre>
</div></div>
<p>with this error</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Jun 10, 2016 11:18:03 AM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: ERROR - Duplicate input: file:/Users/danielcompton/.m2/repository/org/clojure/google-closure-library/0.0-20151016-61277aea/google-closure-library-0.0-20151016-61277aea.jar!/goog/base.js
Jun 10, 2016 11:18:03 AM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 1 error(s), 0 warning(s)
ERROR: JSC_DUPLICATE_INPUT. Duplicate input: file:/Users/danielcompton/.m2/repository/org/clojure/google-closure-library/0.0-20151016-61277aea/google-closure-library-0.0-20151016-61277aea.jar!/goog/base.js at (unknown source) line (unknown line) : (unknown column)</pre>
</div></div>
<p>however the ClojureScript compiler exits successfully without throwing an error. The build looks successful, but the file produced doesn't work. Should the ClojureScript compiler throw on these kinds of errors, or otherwise indicate failure?</p>CLJS-1677Requiring [goog] breaks an :advanced build, but the compiler exits successfullyDefectMinorOpenUnresolvedUnassignedDaniel ComptonThu, 9 Jun 2016 18:27:01 -0500Fri, 10 Jun 2016 08:27:10 -05001.9.3612<p>We should look into why the namespace validation that checks where a ns exists or not isn't already catching this case.</p>Global Rank[CLJS-1827] Improve reader performance on Firefox/Windowshttp://dev.clojure.org/jira/browse/CLJS-1827
ClojureScript<p>cljs.reader/read-string speeds up by a factor of 2 on Firefox/Windows through this change without complicating the code.</p>
<p>(Other JS engines, including Firefox on Linux/Mac do not seem to be affected as significantly.)</p>Firefox on WindowsCLJS-1827Improve reader performance on Firefox/WindowsEnhancementMinorOpenUnresolvedUnassignedMichael SperberperformancereaderThu, 20 Oct 2016 01:58:19 -0500Fri, 21 Oct 2016 05:49:15 -05001.9.7602<p>It would be nice to have a bit more information on this ticket as to what Google Closure does that's unnecessary or whether this path is actually a faithful port of Clojure behavior (copies the implementation of the EDN reader in these hot spots??). Finally the patch names David Frese, have they submitted a CA?</p>
<p>Thanks!</p><p>I believe the Google functions are too general, work on strings in addition to characters etc.</p>
<p>It's not clear to us though why only Firefox on Windows benefits.</p>
<p>(David Frese is a co-worker - yes, has submitted a CA.)</p>Global RankPatchCode[CLJS-1495] Internal ast? assertion for var in fn in defhttp://dev.clojure.org/jira/browse/CLJS-1495
ClojureScript<p>This form, when issued at the REPL, fails to compile, triggering an <tt>ana/ast?</tt> <tt>:pre</tt> violation:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def f (fn [] #'f))</pre>
</div></div>
<p>There appears to be nothing fundamentally wrong with the construct, as it can be worked around in multiple ways.</p>
<p>These workarounds, which move the <tt>var</tt> special out, succeed:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def f (let [vf #'f] (fn [] vf)))</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(declare f)
(let [x (fn [] #'f)] (def f x))</pre>
</div></div>
<p>Also, these subtler workarounds succeed in avoiding the issue: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def f (fn [] #'cljs.user/f))</pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def f (fn x [] #'f))</pre>
</div></div>Also affects 170 (not in pulldown yet)
<br/>
Same behavior in regular and bootstrappedCLJS-1495Internal ast? assertion for var in fn in defDefectMinorOpenUnresolvedUnassignedMike FikesSat, 28 Nov 2015 16:37:56 -0600Sun, 29 Nov 2015 11:08:18 -06001.7.14502<p>Analysis of the issue:</p>
<p>tl;dr: A synthetic local is shadowing the top-level var that the <tt>var</tt> special is being applied to.</p>
<p>Detailed analysis:</p>
<p>The form</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def f (fn [] #'f))</pre>
</div></div>
<p>can be reduced to this simpler self-named form to consider, which also exhibits the issue:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(fn f [] #'f)</pre>
</div></div>
<p>Analyzing <tt>(def f (fn []))</tt> will show that <tt>:fn-self-name true</tt> is set.</p>
<p>A consequence is that the self name, <tt>f</tt> in the running example, is carried into the function body as a <em>local</em> symbol, and thus <tt>f</tt> is no longer a symbol resolving to the top-level var. This leads to a analyzing code that is, in essence, like this sequence</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(declare g)
#'g ;; OK
(let [g 1] #'g) ;; exhibits error</pre>
</div></div>
<p>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 <em>shadowing</em> the top-level var.</p><p>A similar situation occurred for Clojure and that it defeated memoization until fixed <a href="http://dev.clojure.org/jira/browse/CLJ-809">http://dev.clojure.org/jira/browse/CLJ-809</a></p>
<p>Given this</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn fib [n]
(<span class="code-keyword">if</span> (&lt; n 2)
n
(+ (fib (dec n))
(fib (dec (dec n))))))</pre>
</div></div>
<p>Clojure takes a few seconds to compute <tt>(fib 41)</tt> but is instantaneous after <tt>(def fib (memoize fib))</tt>.</p>
<p>The synthetic local defeats this attempt at memoization in ClojureScript.</p>
Global Rank[CLJS-1832] destructuring with #js at :or breaks the compilation when transit is part of the projecthttp://dev.clojure.org/jira/browse/CLJS-1832
ClojureScript<p>Since Om `1.9.293` I was having some compilation issues, I was able to narrow it down to this code:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn f [{:keys [a] :or {a #js {}}}])</pre>
</div></div>
<p>The code above fails to compile when <span class="error">&#91;com.cognitect/transit-clj &quot;0.8.290&quot;&#93;</span> is part of the project dependencies. The problem seems to happen when we try to destructure data at function arguments, using `:or` and having `#js` at part of the `:or`.</p>
<p>I put up a repository with a minimal case here: <a href="https://github.com/wilkerlucio/cljs-compilation-fail">https://github.com/wilkerlucio/cljs-compilation-fail</a></p>
<p>Error stack when compiling:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Wilkers-MacBook-Pro:cljs-compile-bug wilkerlucio$ lein clean &amp;&amp; lein cljsbuild once site
Compiling ClojureScript...
Compiling <span class="code-quote">"resources/<span class="code-keyword">public</span>/site/site.js"</span> from [<span class="code-quote">"src"</span>]...
Compiling <span class="code-quote">"resources/<span class="code-keyword">public</span>/site/site.js"</span> failed.
clojure.lang.ExceptionInfo: failed compiling file:src/cljs_compile_bug/core.cljs {:file #object[java.io.File 0x21399e53 <span class="code-quote">"src/cljs_compile_bug/core.cljs"</span>]}
at clojure.core$ex_info.invokeStatic(core.clj:4725)
at clojure.core$ex_info.invoke(core.clj:4725)
at cljs.compiler$compile_file$fn__4104.invoke(compiler.cljc:1410)
at cljs.compiler$compile_file.invokeStatic(compiler.cljc:1376)
at cljs.compiler$compile_file.invoke(compiler.cljc:1356)
at cljs.closure$compile_file.invokeStatic(closure.clj:432)
at cljs.closure$compile_file.invoke(closure.clj:423)
at cljs.closure$eval6005$fn__6006.invoke(closure.clj:499)
at cljs.closure$eval5941$fn__5942$G__5930__5949.invoke(closure.clj:389)
at cljs.closure$compile_task$fn__6096.invoke(closure.clj:779)
at cljs.closure$compile_task.invokeStatic(closure.clj:777)
at cljs.closure$compile_task.invoke(closure.clj:770)
at cljs.closure$parallel_compile_sources$fn__6102.invoke(closure.clj:806)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invokeStatic(core.clj:657)
at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1963)
at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1963)
at clojure.lang.RestFn.invoke(RestFn.java:425)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.core$apply.invokeStatic(core.clj:661)
at clojure.core$bound_fn_STAR_$fn__6761.doInvoke(core.clj:1993)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.run(AFn.java:22)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.<span class="code-object">Thread</span>.run(<span class="code-object">Thread</span>.java:745)
Caused by: java.lang.RuntimeException: clojure.lang.ArityException: Wrong number of args (1) passed to: analyzer/fn--1412/fn--1413
at com.cognitect.transit.impl.WriterFactory$1.write(WriterFactory.java:64)
at cognitect.transit$write.invokeStatic(transit.clj:149)
at cognitect.transit$write.invoke(transit.clj:146)
at cljs.analyzer$write_analysis_cache.invokeStatic(analyzer.cljc:3320)
at cljs.analyzer$write_analysis_cache.invoke(analyzer.cljc:3307)
at cljs.compiler$emit_source.invokeStatic(compiler.cljc:1307)
at cljs.compiler$emit_source.invoke(compiler.cljc:1237)
at cljs.compiler$compile_file_STAR_$fn__4081.invoke(compiler.cljc:1328)
at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1159)
at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1150)
at cljs.compiler$compile_file_STAR_.invokeStatic(compiler.cljc:1317)
at cljs.compiler$compile_file_STAR_.invoke(compiler.cljc:1313)
at cljs.compiler$compile_file$fn__4104.invoke(compiler.cljc:1398)
... 25 more
Caused by: clojure.lang.ArityException: Wrong number of args (1) passed to: analyzer/fn--1412/fn--1413
at clojure.lang.AFn.throwArity(AFn.java:429)
at clojure.lang.AFn.invoke(AFn.java:32)
at cognitect.transit$write_handler$reify__1328.tag(transit.clj:79)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:147)
at com.cognitect.transit.impl.JsonEmitter.emitMap(JsonEmitter.java:158)
at com.cognitect.transit.impl.AbstractEmitter.emitMap(AbstractEmitter.java:70)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:166)
at com.cognitect.transit.impl.JsonEmitter.emitMap(JsonEmitter.java:158)
at com.cognitect.transit.impl.AbstractEmitter.emitMap(AbstractEmitter.java:70)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:166)
at com.cognitect.transit.impl.AbstractEmitter.emitArray(AbstractEmitter.java:82)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:164)
at com.cognitect.transit.impl.AbstractEmitter.emitArray(AbstractEmitter.java:87)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:164)
at com.cognitect.transit.impl.AbstractEmitter.emitTagged(AbstractEmitter.java:34)
at com.cognitect.transit.impl.AbstractEmitter.emitEncoded(AbstractEmitter.java:59)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:169)
at com.cognitect.transit.impl.AbstractEmitter.emitArray(AbstractEmitter.java:87)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:164)
at com.cognitect.transit.impl.AbstractEmitter.emitTagged(AbstractEmitter.java:34)
at com.cognitect.transit.impl.AbstractEmitter.emitEncoded(AbstractEmitter.java:59)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:169)
at com.cognitect.transit.impl.JsonEmitter.emitMap(JsonEmitter.java:158)
at com.cognitect.transit.impl.AbstractEmitter.emitMap(AbstractEmitter.java:70)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:166)
at com.cognitect.transit.impl.JsonEmitter.emitMap(JsonEmitter.java:158)
at com.cognitect.transit.impl.AbstractEmitter.emitMap(AbstractEmitter.java:70)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:166)
at com.cognitect.transit.impl.JsonEmitter.emitMap(JsonEmitter.java:158)
at com.cognitect.transit.impl.AbstractEmitter.emitMap(AbstractEmitter.java:70)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:166)
at com.cognitect.transit.impl.JsonEmitter.emitMap(JsonEmitter.java:158)
at com.cognitect.transit.impl.AbstractEmitter.emitMap(AbstractEmitter.java:70)
at com.cognitect.transit.impl.AbstractEmitter.marshal(AbstractEmitter.java:166)
at com.cognitect.transit.impl.AbstractEmitter.marshalTop(AbstractEmitter.java:193)
at com.cognitect.transit.impl.JsonEmitter.emit(JsonEmitter.java:28)
at com.cognitect.transit.impl.WriterFactory$1.write(WriterFactory.java:61)
... 37 more
Subprocess failed</pre>
</div></div>CLJS-1832destructuring with #js at :or breaks the compilation when transit is part of the projectDefectMinorOpenUnresolvedUnassignedWilker Lúcio da SilvaSun, 23 Oct 2016 06:10:31 -0500Sun, 23 Oct 2016 09:11:01 -05001.9.29301Global Rank[CLJS-1830] sorted-map-by returns values for non-existing keyshttp://dev.clojure.org/jira/browse/CLJS-1830
ClojureScript<p>Run the following in a REPL:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def a (sorted-map-by &gt; 1 :a 2 :b))
(get a <span class="code-quote">"a"</span>)</pre>
</div></div>
<p>Expected: <tt>nil</tt> or exception</p>
<p>Actual: <tt>:a</tt></p>Oracle Java 1.8.0_91
<br/>
Apache Maven 3.3.9CLJS-1830sorted-map-by returns values for non-existing keysDefectMinorOpenUnresolvedUnassignedEugene PakhomovSat, 22 Oct 2016 03:55:40 -0500Sun, 23 Oct 2016 09:12:00 -05001.9.29301Global Rank[CLJS-1634] Track bound dynamic variables to support binding in async mechanisms.http://dev.clojure.org/jira/browse/CLJS-1634
ClojureScript<p>The issue has been raised before:</p>
<ul class="alternate" type="square">
<li><a href="https://groups.google.com/forum/#!topic/clojure/6cmnkHmHBNw">https://groups.google.com/forum/#!topic/clojure/6cmnkHmHBNw</a></li>
<li><a href="http://dev.clojure.org/display/design/Dynamic+Binding">http://dev.clojure.org/display/design/Dynamic+Binding</a></li>
</ul>
<p>While the reasoning behind the proposal is still valid, the original approach has made no progress due to the performance penalty. I have implemented a simplified approach with mutable JavaScript datastructures to minimize the performance impact. Because we are single-threaded we can use js assignment and don't need to port Clojure's binding frame. A small penalty is paid by the user of binding (see benchmark8) and a higher one by async mechanisms capturing and restoring the bindings (benchmark1-7):</p>
<p><a href="https://gist.github.com/whilo/a8ef2cd3f0e033d3973880a2001be32a">https://gist.github.com/whilo/a8ef2cd3f0e033d3973880a2001be32a</a></p>
<p>I would provide patches to ClojureScript, if this looks like a worthwhile approach.</p>
Any cljs version.CLJS-1634Track bound dynamic variables to support binding in async mechanisms.EnhancementMinorOpenUnresolvedUnassignedChristian WeilbachcljsenhancementTue, 26 Apr 2016 10:29:07 -0500Sat, 20 Aug 2016 05:37:19 -05001.7.22812<p>Just for record I commented on it here: <a href="https://gist.github.com/whilo/a8ef2cd3f0e033d3973880a2001be32a#gistcomment-1764489">https://gist.github.com/whilo/a8ef2cd3f0e033d3973880a2001be32a#gistcomment-1764489</a>. Not sure if GitHub sends out notifications about new gist comments.</p><p>Thanks for pointing it out. David Nolen has also pointed out prototype chains to address this issue and now I see what he meant. I am not familiar enough with the internals of "this" in JavaScript, but one problem I see is that you need to distinguish dynamic vars at the call site. The advantage of using an object directly and capturing and restoring the frame explicitly when you enter and leave the code is that call sites are totally unaffected. The cost is only paid a little at the binding site and mostly in async libraries (bound-fn). But I might still need to look further into "this" <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/>. I have not got the gist comment from github.</p><p>Correct. </p>
<p>&gt; you need to distinguish dynamic vars at the call site</p>
<p>I agree. My initial motivation was to solve a bit different problem without cooperation from library authors. I didn't want to modify ClojureScript behaviour and wanted to be just touching own code or doing trivial changes in library forks. Just wanted to share my thoughts about the implementation.</p>
<p>I have a feeling that solving this "async context" problem will be difficult. You will need async library authors to adapt their libraries. And users unaware of this will be running into issues anytime they step outside of bound-fn aware async libraries (for example using raw js interop). I believe Angular people solved this robustly in <a href="https://github.com/angular/zone.js">https://github.com/angular/zone.js</a>. The implementation is quite scary monkey-patching, but if they were able to wrap all existing async calls at lowest level, maybe we could just build on top of their foundation and use zone.js as parallel mechanism for `binding`.</p><p>The angle I am coming from is roughly described here: <a href="https://github.com/fullcontact/full.monty/pull/9#issuecomment-131152058">https://github.com/fullcontact/full.monty/pull/9#issuecomment-131152058</a></p>
<p>I only found out at the very end when I had supervision of go-channels completely implemented, that the cljs binding was not behaving like the Clojure one. Arguments pro/contra binding in Clojure are also referenced. The zone monkey patching looks very heavy and prone to cause hairy bugs. It is noteworthy that Clojure does not embrace bindings, but keeps them always thread-local. So there you also have to use bound-fn or something similar whenever code is executed concurrently. core.async for instance uses the Clojure mechanism to push (capture) and pop (restore) bindings. I would like to have this in ClojureScript as well. I think one should not retain all bindings automatically, but rather allow the library author to handle dynamic bindings. I only track the supervisor binding for instance. For ClojureScript as for Clojure libraries and wrappers this should be fine. Pure JavaScript libraries usually have their own binding concepts like zone.js, right? </p>
<p>Tracking bindings is neither for free in Clojure nor in ClojureScript and it is an important design goal to embrace the host. In fact originally I tried to capture and restore all bindings. My benchmarks for tracking more dynamic vars (instead of just the currently active binding), were linearly more expansive than rebinding fewer selected vars and become prohibitive when you reach a few hundred. </p><p>I would be happy if your proposal went through. It would help my use-cases as well.</p>
<p>I'm going to explore zone.js when I get some spare time. I will try do write a wrapper library and implement an alternative mechanism to bindings using zone.js. I would like to provide this functionality as a library without a need to modify ClojureScript compiler or involvement from library authors.</p><p>Ok, I am curious how well this will work. Would this work with the state-machine transformation of core.async? </p><p>I believe so. Core.async state machine uses only setTimeout and goog.async.nextTick. We can teach zone.js to deal with nextTick by setting goog.async.nextTick.wrapCallback_ with zone wrapping. Also if user decided to use any async API in their go blocks it should work, because zone.js will carry proper zone binding over async boundaries.</p><p>I have opened this issue in zone.js: <a href="https://github.com/angular/zone.js/issues/342">https://github.com/angular/zone.js/issues/342</a></p><p>Hey. Have you made any progress with implementing a small cljs demo with zone.js yet?</p><p>Hi Christian. No, unfortunately I didn't get to it.</p><p>Interestingly to implement the Common Lisp like condition system chouser presented here <a href="https://www.youtube.com/watch?v=zp0OEDcAro0">https://www.youtube.com/watch?v=zp0OEDcAro0</a> the dynamic binding working over async boundaries is also important.</p><p>Christian, please have a look at my implementation:<br/>
<a href="https://github.com/binaryage/cljs-zones">https://github.com/binaryage/cljs-zones</a></p>
<p>I have implemented the prototype trick as a library. It is just a gist of the idea, didn't spend time to make it robust yet and ES3-compatible. Re-binding frames should be as cheap as changing pointers (inside JS runtime).</p><p>Very nice work! I am checking it out atm. Nice that it is self-contained. (The Klipse version throws a goog.object not found error for me btw.)</p><p>I have updated the gist to incorporate cljs-zones in benchmark 8, 9 and 10. It is a bit faster in restoring dynamic bindings, but not much:</p>
<p><a href="https://gist.github.com/whilo/a8ef2cd3f0e033d3973880a2001be32a">https://gist.github.com/whilo/a8ef2cd3f0e033d3973880a2001be32a</a></p>
<p>But there is a significant performance penalty on var access:</p>
<p>full.binding_test.benchmark10()<br/>
core.cljs:150 [], ((fn [] v1)), 10000 runs, 1 msecs<br/>
core.cljs:150 [], ((fn [] (zones/get v1))), 10000 runs, 4 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
core.cljs:150 [], ((fn [] v1)), 10000 runs, 2 msecs<br/>
core.cljs:150 [], ((fn [] (zones/get v1))), 10000 runs, 6 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
core.cljs:150 [], ((fn [] v1)), 10000 runs, 3 msecs<br/>
core.cljs:150 [], ((fn [] (zones/get v1))), 10000 runs, 4 msecs</p>
<p>Is this penalty addressable? </p>
<p>One other issue is that JavaScript prototype manipulations through "this" would interfere with the cljs binding mechanism, but this might be acceptable.</p><p>Thanks for measuring it. I didn't really get to benchmarking yet.</p>
<p>Did you run the benchmarks under :advanced optimizations?</p>
<p>zones/get currently emits a call to goog.object/get, I'm not sure if this gets inlined by closure compiler, but if not, we can probably improve it by generating raw js object access:<br/>
<a href="https://github.com/binaryage/cljs-zones/blob/fdfa1421c39d64c9c6b9efbff474b7677f908197/src/lib/zones/core.clj#L94">https://github.com/binaryage/cljs-zones/blob/fdfa1421c39d64c9c6b9efbff474b7677f908197/src/lib/zones/core.clj#L94</a></p>
<p>&gt; One other issue is that JavaScript prototype manipulations through "this" would interfere with the cljs binding mechanism<br/>
Can you elaborate? I don't understand how it would interfere.</p><p>With advanced compilation I get:</p>
<p>full.binding_test.benchmark10()<br/>
client.js:278 [], ((fn [] v1)), 10000 runs, 1 msecs<br/>
client.js:278 [], ((fn [] (zones/get v1))), 10000 runs, 2 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
client.js:278 [], ((fn [] v1)), 10000 runs, 2 msecs<br/>
client.js:278 [], ((fn [] (zones/get v1))), 10000 runs, 3 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
client.js:278 [], ((fn [] v1)), 10000 runs, 3 msecs<br/>
client.js:278 [], ((fn [] (zones/get v1))), 10000 runs, 2 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
client.js:278 [], ((fn [] v1)), 10000 runs, 1 msecs<br/>
client.js:278 [], ((fn [] (zones/get v1))), 10000 runs, 2 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
client.js:278 [], ((fn [] v1)), 10000 runs, 1 msecs<br/>
client.js:278 [], ((fn [] (zones/get v1))), 10000 runs, 3 msecs<br/>
null<br/>
full.binding_test.benchmark10()<br/>
client.js:278 [], ((fn [] v1)), 10000 runs, 1 msecs<br/>
client.js:278 [], ((fn [] (zones/get v1))), 10000 runs, 1 msecs</p>
<p>But this is a very simple test. If you see a better way to benchmark it, go ahead <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/>. When the chains get prototype chains get longer, it might be more painful to walk the chain for each global lookup.</p>
<p>&gt; Can you elaborate? I don't understand how it would interfere.<br/>
There has been a proposal somewhere to pass "this" in all cljs functions instead of null as first argument. Your explicit model of a zone is pretty safe I think, but if people would interefere with prototypes in JS, then this might break the "this" approach in subtle ways. Without passing "this" as a direct argument and doing it in a more JS way, you have to setup the zones all the time instead of using the scope chain, which might also contribute to the managing cost. So the "this" approach might help with performance, but I am not sure. You still have the chain overhead. But I am no JS expert, you know much better than me what you are doing. </p><p>My last comment was a little bit confusing. I only see the problem with an impact on dereferencing vars. In the benchmark above the prototype chain is very short (v1 can be directly resolved) and already has a significant penalty, but I think the penalty gets even worse for not rebound root vars if you have a higher nesting level for the binding and the chain gets longer. Can you address this somehow? </p>Global Rank[CLJS-1838] cljs.compiler.api/compile-root doesn't use .cljc/.cljs precedence rules correctly.http://dev.clojure.org/jira/browse/CLJS-1838
ClojureScript<p>When you have both a .cljc and a .cljs for the same namespace, <tt>compile-root</tt> seems to arbitrarily choose which gets compiled. Case-in-point: cljs.test.</p>CLJS-1838cljs.compiler.api/compile-root doesn't use .cljc/.cljs precedence rules correctly.DefectMinorOpenUnresolvedUnassignedMike KaplinskiyThu, 3 Nov 2016 19:16:31 -0500Sat, 5 Nov 2016 09:29:25 -050002<p>What ClojureScript version was this tested against? It would seem to me that <a href="http://dev.clojure.org/jira/browse/CLJS-1772" title="Dependency index can incorrectly add `.cljc` files instead of `.cljs` if both are present"><del>CLJS-1772</del></a> fixed this issue (which was shipped in 1.9.229).</p>Global Rank[CLJS-1841] Check lib folder before compiling with cljsc, check for compilation success before running testshttp://dev.clojure.org/jira/browse/CLJS-1841
ClojureScript<p>If script/bootstrap hasn't been run, then running script/test returns the slightly cryptic error message:</p>
<p> Error: Could not find or load main class clojure.main</p>
<p>This patch checks if the lib folder exists and has files in it. If not it prompts the user to run script/bootstrap and exits.</p>
<p>This patch also adds a check for compilation success before running tests against the various VM engines.</p>CLJS-1841Check lib folder before compiling with cljsc, check for compilation success before running testsEnhancementMinorOpenUnresolvedUnassignedDaniel ComptonSun, 6 Nov 2016 16:47:19 -0600Sun, 6 Nov 2016 16:47:49 -060000Global RankPatchCode[CLJS-1734] :import in ns silently discards imported classes with the same namehttp://dev.clojure.org/jira/browse/CLJS-1734
ClojureScript<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns some.ns
(:<span class="code-keyword">import</span> goog.fx.Transition.EventType
goog.history.EventType))</pre>
</div></div>
<p>Both classes are named <tt>EventType</tt> and the second will effectively remove the first one without warning or error.</p>CLJS-1734:import in ns silently discards imported classes with the same nameDefectMinorOpenUnresolvedUnassignedThomas HellernewbieThu, 11 Aug 2016 04:23:21 -0500Mon, 7 Nov 2016 09:18:40 -060002Global Rank[CLJS-1646] Internal compiler error when importing Showdown via CommonJShttp://dev.clojure.org/jira/browse/CLJS-1646
ClojureScript<p>Hi!</p>
<p>I am trying to use Showdown 1.4.1 from NPM <span class="error">&#91;1&#93;</span> using a `:commonjs` foreign-lib. Sadly, compilation crashes with the following error:</p>
<p>java.lang.RuntimeException: INTERNAL COMPILER ERROR.<br/>
Please report this problem.</p>
<p>null<br/>
Node(SCRIPT): node_modules/showdown/dist/showdown.js:1:0<br/>
<span class="error">&#91;source unknown&#93;</span><br/>
Parent: NULL<br/>
at com.google.javascript.jscomp.ES6ModuleLoader.normalizeInputAddress(ES6ModuleLoader.java:118)<br/>
at com.google.javascript.jscomp.ProcessCommonJSModules.inputToModuleName(ProcessCommonJSModules.java:89)<br/>
at com.google.javascript.jscomp.ProcessCommonJSModules$ProcessCommonJsModulesCallback.visitScript(ProcessCommonJSModules.java:336)<br/>
at com.google.javascript.jscomp.ProcessCommonJSModules$ProcessCommonJsModulesCallback.visit(ProcessCommonJSModules.java:245)<br/>
at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:623)<br/>
at com.google.javascript.jscomp.NodeTraversal.traverse(NodeTraversal.java:297)<br/>
at com.google.javascript.jscomp.NodeTraversal.traverseEs6(NodeTraversal.java:564)<br/>
at com.google.javascript.jscomp.ProcessCommonJSModules.process(ProcessCommonJSModules.java:85)<br/>
at cljs.closure$eval5486$fn__5487.invoke(closure.clj:1541)<br/>
at clojure.lang.MultiFn.invoke(MultiFn.java:233)<br/>
at cljs.closure$write_javascript.invokeStatic(closure.clj:1601)<br/>
at cljs.closure$write_javascript.invoke(closure.clj:1578)<br/>
at cljs.closure$source_on_disk.invokeStatic(closure.clj:1624)<br/>
at cljs.closure$source_on_disk.invoke(closure.clj:1619)<br/>
at cljs.closure$output_unoptimized$fn__5536.invoke(closure.clj:1662)<br/>
at clojure.core$map$fn__4785.invoke(core.clj:2646)<br/>
at clojure.lang.LazySeq.sval(LazySeq.java:40)<br/>
at clojure.lang.LazySeq.seq(LazySeq.java:49)<br/>
at clojure.lang.RT.seq(RT.java:521)<br/>
at clojure.core$seq__4357.invokeStatic(core.clj:137)<br/>
at clojure.core$filter$fn__4812.invoke(core.clj:2700)<br/>
at clojure.lang.LazySeq.sval(LazySeq.java:40)<br/>
at clojure.lang.LazySeq.seq(LazySeq.java:49)<br/>
at clojure.lang.RT.seq(RT.java:521)<br/>
at clojure.core$seq__4357.invokeStatic(core.clj:137)<br/>
at clojure.core$map$fn__4785.invoke(core.clj:2637)<br/>
at clojure.lang.LazySeq.sval(LazySeq.java:40)<br/>
at clojure.lang.LazySeq.seq(LazySeq.java:49)<br/>
at clojure.lang.Cons.next(Cons.java:39)<br/>
at clojure.lang.RT.next(RT.java:688)<br/>
at clojure.core$next__4341.invokeStatic(core.clj:64)<br/>
at clojure.core$str$fn__4419.invoke(core.clj:546)<br/>
at clojure.core$str.invokeStatic(core.clj:544)<br/>
at clojure.core$str.doInvoke(core.clj:533)<br/>
at clojure.lang.RestFn.applyTo(RestFn.java:139)<br/>
at clojure.core$apply.invokeStatic(core.clj:646)<br/>
at clojure.core$apply.invoke(core.clj:641)<br/>
at cljs.closure$deps_file.invokeStatic(closure.clj:1340)<br/>
at cljs.closure$deps_file.invoke(closure.clj:1337)<br/>
at cljs.closure$output_deps_file.invokeStatic(closure.clj:1360)<br/>
at cljs.closure$output_deps_file.invoke(closure.clj:1359)<br/>
at cljs.closure$output_unoptimized.invokeStatic(closure.clj:1670)<br/>
at cljs.closure$output_unoptimized.doInvoke(closure.clj:1653)<br/>
at clojure.lang.RestFn.applyTo(RestFn.java:139)<br/>
at clojure.core$apply.invokeStatic(core.clj:648)<br/>
at clojure.core$apply.invoke(core.clj:641)<br/>
at cljs.closure$build.invokeStatic(closure.clj:1981)<br/>
at cljs.closure$build.invoke(closure.clj:1882)<br/>
at cljs.build.api$build.invokeStatic(api.clj:210)<br/>
at cljs.build.api$build.invoke(api.clj:198)<br/>
at cljs.build.api$build.invokeStatic(api.clj:201)<br/>
at cljs.build.api$build.invoke(api.clj:198)<br/>
at cljsbuild.compiler$compile_cljs$fn__5771.invoke(compiler.clj:60)<br/>
at cljsbuild.compiler$compile_cljs.invokeStatic(compiler.clj:59)<br/>
at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:48)<br/>
at cljsbuild.compiler$run_compiler.invokeStatic(compiler.clj:168)<br/>
at cljsbuild.compiler$run_compiler.invoke(compiler.clj:122)<br/>
at user$eval5908$iter_<em>5944</em><em>5948$fn</em><em>5949$fn</em>_5967.invoke(form-init8819033363931377476.clj:1)<br/>
at user$eval5908$iter_<em>5944</em><em>5948$fn</em>_5949.invoke(form-init8819033363931377476.clj:1)<br/>
at clojure.lang.LazySeq.sval(LazySeq.java:40)<br/>
at clojure.lang.LazySeq.seq(LazySeq.java:49)<br/>
at clojure.lang.RT.seq(RT.java:521)<br/>
at clojure.core$seq__4357.invokeStatic(core.clj:137)<br/>
at clojure.core$dorun.invokeStatic(core.clj:3024)<br/>
at clojure.core$doall.invokeStatic(core.clj:3039)<br/>
at clojure.core$doall.invoke(core.clj:3039)<br/>
at user$eval5908.invokeStatic(form-init8819033363931377476.clj:1)<br/>
at user$eval5908.invoke(form-init8819033363931377476.clj:1)<br/>
at clojure.lang.Compiler.eval(Compiler.java:6927)<br/>
at clojure.lang.Compiler.eval(Compiler.java:6917)<br/>
at clojure.lang.Compiler.load(Compiler.java:7379)<br/>
at clojure.lang.Compiler.loadFile(Compiler.java:7317)<br/>
at clojure.main$load_script.invokeStatic(main.clj:275)<br/>
at clojure.main$init_opt.invokeStatic(main.clj:277)<br/>
at clojure.main$init_opt.invoke(main.clj:277)<br/>
at clojure.main$initialize.invokeStatic(main.clj:308)<br/>
at clojure.main$null_opt.invokeStatic(main.clj:342)<br/>
at clojure.main$null_opt.invoke(main.clj:339)<br/>
at clojure.main$main.invokeStatic(main.clj:421)<br/>
at clojure.main$main.doInvoke(main.clj:384)<br/>
at clojure.lang.RestFn.invoke(RestFn.java:421)<br/>
at clojure.lang.Var.invoke(Var.java:383)<br/>
at clojure.lang.AFn.applyToHelper(AFn.java:156)<br/>
at clojure.lang.Var.applyTo(Var.java:700)<br/>
at clojure.main.main(main.java:37)<br/>
Caused by: java.lang.NullPointerException<br/>
... 85 more</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://www.npmjs.com/package/showdown">https://www.npmjs.com/package/showdown</a></p>cljs 1.8.51, clojure 1.8, lein-cljsbuild 1.1.3CLJS-1646Internal compiler error when importing Showdown via CommonJSDefectMinorOpenUnresolvedUnassignedJuan Pedro Bolivar PuenteTue, 24 May 2016 12:34:19 -0500Mon, 7 Nov 2016 09:40:53 -060003<p>Forgot to mention, this is the line in my :foreign-libs</p>
<p>{:file "node_modules/showdown/dist/showdown.js"<br/>
:provides <span class="error">&#91;&quot;showdown&quot;&#93;</span><br/>
:module-type :commonjs}</p>
<p>Same problem occurs if I use showdown.min.js</p><p>Can't repro in ClojureScript 1.9.293. Showdown seems to be correctly consumed by the Closure Compiler.</p><p>FWIW, it also works for me in 1.8.51, could this related to tooling / dependency conflicts?</p>Global Rank[CLJS-1604] Self-host: cljs.js/compile-str causes a javascript errorhttp://dev.clojure.org/jira/browse/CLJS-1604
ClojureScript<p>When requiring `cljs.js` and calling `cljs.js/compile-str` with `:optimizations :advanced`<br/>
I get the following error in the browser: <br/>
"Uncaught TypeError: Cannot set property 'rd' of undefined"</p>
<p>Steps to reproduce:</p>
<p>1. Make a directory<br/>
2. Copy shipping cljs.jar into the directory<br/>
3. Make an index.html, src/hello_world/core.cljs, and build.clj file with contents as below.<br/>
4. java -cp cljs.jar:src clojure.main build.clj<br/>
5. Open index.html with Chrome and view the JavaScriptConsole in Chrome.</p>
<p>index.html:</p>
<p>&lt;html&gt;<br/>
&lt;body&gt;<br/>
&lt;script type="text/javascript" src="out/main.js"&gt;&lt;/script&gt;<br/>
&lt;/body&gt;<br/>
&lt;/html&gt;<br/>
src/hello_world/core.cljs:<br/>
(ns hello-world.core<br/>
(:require <span class="error">&#91;cljs.js :as cljs&#93;</span>))</p>
<p>(set! (.. js/window -cljs -user) #js {})</p>
<p>(cljs/compile-str (cljs/empty-state) "" indentity)</p>
<p>build.clj:</p>
<p>(require 'cljs.build.api)</p>
<p>(cljs.build.api/build "src"<br/>
{:output-to "out/main.js"<br/>
:optimizations :whitespace})</p>
<p>(System/exit 0)</p>
CLJS-1604Self-host: cljs.js/compile-str causes a javascript errorDefectMinorOpenUnresolvedUnassignedYehonathan SharvitbootstrapbugSat, 19 Mar 2016 17:28:40 -0500Thu, 14 Apr 2016 07:02:50 -05001.7.22802<p>I need to fix the title of the issue: "Self-host: in advanced compilation - cljs.js/compile-str causes a javascript error"</p><p>You can only use up to <tt>:optimizations :simple</tt> with self-host. See <a href="https://github.com/clojure/clojurescript/wiki/Optional-Self-hosting#production-builds">https://github.com/clojure/clojurescript/wiki/Optional-Self-hosting#production-builds</a></p>
<p>Discussion: One rationale for this is that the emitted code, in order to be executable, needs access to non-Closure-munged/DCEd symbols from the standard ClojureScript lib. Perhaps this limitation need only exist for <tt>eval-str</tt>, (while not for <tt>compile-str</tt>, <tt>analyze-str</tt>, etc.)</p><p>I'd recommend closing this as declined (no plans exist to support self-host with <tt>:advanced</tt>).</p>Global Rank[CLJS-1473] Require fail on ns/in-ns created namespaceshttp://dev.clojure.org/jira/browse/CLJS-1473
ClojureScript<p>Just to report that the following does not work at the repl (in Clojure it does):</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(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.<span class="code-object">Compiler</span>.eval(<span class="code-object">Compiler</span>.java:6782)
at clojure.lang.<span class="code-object">Compiler</span>.eval(<span class="code-object">Compiler</span>.java:6772)
at clojure.lang.<span class="code-object">Compiler</span>.load(<span class="code-object">Compiler</span>.java:7227)
at clojure.lang.<span class="code-object">Compiler</span>.loadFile(<span class="code-object">Compiler</span>.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)</pre>
</div></div>
<p>I am available for investigating more and/or taking charge of the issue.</p>3.13.0-65 x86_64 GNU/LinuxCLJS-1473Require fail on ns/in-ns created namespacesDefectMinorOpenUnresolvedUnassignedAndrea RichiardibugTue, 20 Oct 2015 21:26:30 -0500Wed, 21 Oct 2015 14:37:51 -05001.7.14502<p>sorry about the mistakes...how to edit?</p><p>Confirmed using NodeJs repl:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript Node.js REPL server listening on 51885
Watch compilation log available at: out/watch.log
To quit, type: :cljs/quit
cljs.user=&gt; (in-ns 'ns.core)
nil
ns.core=&gt; (def a 3)
#'ns.core/a
ns.core=&gt; (in-ns 's.core.repl)
nil
s.core.repl=&gt; (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.<span class="code-object">Compiler</span>.eval(<span class="code-object">Compiler</span>.java:6782)
at clojure.lang.<span class="code-object">Compiler</span>.load(<span class="code-object">Compiler</span>.java:7227)
at clojure.lang.<span class="code-object">Compiler</span>.loadFile(<span class="code-object">Compiler</span>.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)</pre>
</div></div> <p>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 &#42;load-fn&#42; out there?</p><p>I am analyzing `cljs.repl/load-namespace` and it looks like it handles only loading from sources:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">line 178 @ clojurescript 1.7.158
sources (cljsc/add-dependencies
(merge (env-&gt;opts repl-env) opts)
{:requires [(name ns)]
:type :seed
:url (:uri (cljsc/source-<span class="code-keyword">for</span>-namespace
ns env/*compiler*))})</pre>
</div></div>
<p>The function `cljs.closure/source-for-namespace` is throwing the exception because of course it cannot find the sources for a manually created namespace.<br/>
An idea could be to change `cljs.closure/source-for-namespace` and return nil in case no sources can be found.<br/>
Then change `cljs.repl/load-namespace` to check for created namespaces when `souces` is nil.</p>
<p>Mike told me that the namespaces are not reified, so the next question is, is there an atom that contains all the created namespaces?</p>
<p>I am going to wait for input on this, when everybody has time of course.</p>Global Rank[CLJS-1843] EDN analysis cache may write unusable datahttp://dev.clojure.org/jira/browse/CLJS-1843
ClojureScript<p>EDN has a built-in default writer for all objects, this may cause the cache to write something like <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">#object[Thing <span class="code-quote">"thing-str"</span>]</pre>
</div></div> that cannot be read to construct an actual <tt>Thing</tt> instance.</p>
<p>This leads to an issue when trying to use the analysis data since it will contain different things when coming from cache or not.</p>
<p>This issue was highlighted by transit since it has no default writer and didn't know how to encode JSValue. <span class="error">&#91;1&#93;</span> Instead of writing something unusable it failed early.</p>
<p>The cache write should rather gracefully fail (and warn) instead of writing unusable data or exploding.</p>
<p><span class="error">&#91;1&#93;</span> <a href="http://dev.clojure.org/jira/browse/CLJS-1666">http://dev.clojure.org/jira/browse/CLJS-1666</a></p>CLJS-1843EDN analysis cache may write unusable dataDefectMinorOpenUnresolvedUnassignedThomas HellerTue, 8 Nov 2016 04:06:47 -0600Tue, 8 Nov 2016 04:15:10 -060001Global Rank[CLJS-1795] Support more options in the `:closure-warnings` compiler optionhttp://dev.clojure.org/jira/browse/CLJS-1795
ClojureScript<p>Support more options in the `:closure-warnings` compiler option as per <a href="https://github.com/google/closure-compiler/wiki/Warnings#warnings-categories">https://github.com/google/closure-compiler/wiki/Warnings#warnings-categories</a></p>CLJS-1795Support more options in the `:closure-warnings` compiler optionEnhancementMinorOpenUnresolvedUnassignedAntónio Nuno MonteiroWed, 28 Sep 2016 09:38:19 -0500Tue, 8 Nov 2016 14:14:33 -0600Next00Global Rank[CLJS-1544] cljs.test REPL reload supporthttp://dev.clojure.org/jira/browse/CLJS-1544
ClojureScript<p>When adding a test to a test ns that uses cljs.test and re-loading (via require + :reload) that namespace in the REPL after saving the file - invoking run-tests does not include the newly added test.</p>CLJS-1544cljs.test REPL reload supportDefectMinorOpenUnresolvedUnassignedDavid NolenWed, 13 Jan 2016 14:37:49 -0600Tue, 8 Nov 2016 14:14:33 -06001.7.228Next01Global Rank[CLJS-1485] Error when requiring `goog` namespace in a ns declaration http://dev.clojure.org/jira/browse/CLJS-1485
ClojureScript<p>I wanted to use functions from <em>goog</em> namespace although--as I found out later, I didn't have to because <em>goog</em> is already exists in my namespace. So, I put (:require <span class="error">&#91;goog&#93;</span>) in a ns declaration. Then, when I tried to reload that particular namespace by doing <tt>:require</tt> <tt>:reload</tt> in a cljs repl, I got: </p>
<blockquote><p>Error: Namespace "x.x.x" already declared. </p></blockquote>
<p>Doing :require :reload again in the cljs repl makes the repl throws </p>
<blockquote>
<p>Error: Namespace "cljs.user" already declared.<br/>
(NO_SOURCE_FILE)<br/>
(out/goog/base.js:273:40)</p></blockquote>
<p>I tested the steps below using clojurescript <b>1.7.145</b> and <b>1.7.170</b>.</p>
<p>Here are the steps to reproduce which are taken from clojurescript quickstart-browser repl section:</p>
<p>1. Download the standalone clojurescript 1.7.170 jar <a href="https://github.com/clojure/clojurescript/releases/download/r1.7.170/cljs.jar">https://github.com/clojure/clojurescript/releases/download/r1.7.170/cljs.jar</a></p>
<p>2. Create a directory hello_world and copy the JAR into that directory, then from inside the hello_world directory:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>mkdir -p src/hello_world;touch repl.clj;touch index.html;touch src/hello_world/core.cljs
</pre>
</div></div>
<p>3. repl.clj content</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(require 'cljs.repl)
(require 'cljs.build.api)
(require 'cljs.repl.browser)
(cljs.build.api/build "src"
{:main 'hello-world.core
:output-to "out/main.js"
:verbose true})
(cljs.repl/repl (cljs.repl.browser/repl-env)
:watch "src"
:output-dir "out")
</pre>
</div></div>
<p>4. index.html content</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>&lt;html&gt;
&lt;body&gt;
&lt;script type="text/javascript" src="out/main.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
</div></div>
<p>5. src/hello_world/core.cljs content</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(ns hello-world.core
(:require [clojure.browser.repl :as repl]))
(defonce conn
(repl/connect "http://localhost:9000/repl"))
(enable-console-print!)
(println "Hello world!")
(defn foo [a b]
(+ a b))
</pre>
</div></div>
<p>6. run clojurescript repl</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>java -cp cljs.jar:src clojure.main repl.clj
</pre>
</div></div>
<p>7. Open <a href="http://localhost:9000">http://localhost:9000</a> in browser (I use google chrome). Open javascript console.</p>
<p>8. enter expression below in the clojurescript repl</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(require '[hello-world.core :as hello] :reload)
</pre>
</div></div>
<p>10. Look the browser javascript console. Nothing new shown.</p>
<p>11. Quit from the repl using <tt>:cljs/quit</tt></p>
<p>12. Add <span class="error">&#91;goog&#93;</span> in ns declaration in <tt>src/hello_world/core.cljs</tt> so that the content of the file becomes:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(ns hello-world.core
(:require [clojure.browser.repl :as repl]
[goog]))
(defonce conn
(repl/connect "http://localhost:9000/repl"))
(enable-console-print!)
(println "Hello world!")
(defn foo [a b]
(+ a b))
</pre>
</div></div>
<p>13. Run the clojurescript repl again </p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>java -cp cljs.jar:src clojure.main repl.clj
</pre>
</div></div>
<p>14. Now refresh the <a href="http://localhost:9000">http://localhost:9000</a> in browser. Make sure the javascript console stays open.</p>
<p>13. enter expression below in the clojurescript repl</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(require '[hello-world.core :as hello] :reload)
;;=&gt; nil
</pre>
</div></div>
<p>it just returns nil</p>
<p>15. See the javascript console, it shows</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>Uncaught Error: Namespace "hello_world.core" already declared.
</pre>
</div></div>
<p>16. Executing this expression again (require '<span class="error">&#91;hello-world.core :as hello&#93;</span> :reload) shows nothing new in the browser's javascript console while the clojurescript repl throws</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>Error: Namespace "cljs.user" already declared.
(NO_SOURCE_FILE)
(out/goog/base.js:273:40)
</pre>
</div></div>CLJS-1485Error when requiring `goog` namespace in a ns declaration DefectMinorOpenUnresolvedUnassignedAvicennaTue, 10 Nov 2015 10:24:43 -0600Tue, 8 Nov 2016 14:14:33 -06001.7.145Next00Global Rank[CLJS-1453] cljs.compiler/load-libs does not preserve user expressed require orderhttp://dev.clojure.org/jira/browse/CLJS-1453
ClojureScript<p>Due to putting the requires into a map the original order is lost. This is a problem primarily when order specific side effects are present in the required namespaces.</p>CLJS-1453cljs.compiler/load-libs does not preserve user expressed require orderDefectMinorOpenUnresolvedUnassignedDavid NolenThu, 17 Sep 2015 08:06:54 -0500Tue, 8 Nov 2016 14:14:33 -06001.7.145Next03Global Rank[CLJS-1419] enhance numeric inference, if + number? test on local var should tag local var in the successful branchhttp://dev.clojure.org/jira/browse/CLJS-1419
ClojureScriptCLJS-1419enhance numeric inference, if + number? test on local var should tag local var in the successful branchEnhancementMinorOpenUnresolvedUnassignedDavid NolenWed, 12 Aug 2015 06:11:52 -0500Tue, 8 Nov 2016 14:14:33 -06001.7.145Next00<p>One small complication is dealing with <tt>and</tt> as it has an optimizing case.</p>Global Rank[CLJS-1412] Add JSDoc type information to individual IFn methodshttp://dev.clojure.org/jira/browse/CLJS-1412
ClojureScript<p>Propagate user supplied docstring type information to the various fn arities so that more code may be checked.</p>CLJS-1412Add JSDoc type information to individual IFn methodsEnhancementMinorOpenUnresolvedUnassignedDavid Nolentype-checkMon, 10 Aug 2015 07:30:59 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next00Global Rank[CLJS-1315] Warning on Google Closure enum property access with /http://dev.clojure.org/jira/browse/CLJS-1315
ClojureScript<p>Edge case in / usage, <tt>EventType/CLICK</tt> does not trigger a warning. Foo/bar always means that Foo is a namespace, it cannot be used for the static field access pattern common in Java as there's no reflection information in JavaScript to determine this.</p>CLJS-1315Warning on Google Closure enum property access with /DefectMinorOpenUnresolvedUnassignedDavid NolenThu, 18 Jun 2015 16:53:06 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next01Global Rank[CLJS-1286] REPL environment should be able to provide advice if source mapping failshttp://dev.clojure.org/jira/browse/CLJS-1286
ClojureScript<p>For example browser REPL will often need users to supply <tt>:host-port</tt>, <tt>:host</tt>, and <tt>:asset-path</tt> in order to correctly parse files from stacktraces.</p>CLJS-1286REPL environment should be able to provide advice if source mapping failsDefectMinorOpenUnresolvedUnassignedDavid NolenSat, 23 May 2015 19:41:53 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next00Global Rank[CLJS-1271] Missing warning when assigning namespaces via defhttp://dev.clojure.org/jira/browse/CLJS-1271
ClojureScript<p>Currently you can assign a Closure namespace to a var without getting a warning.</p>
<p>Minimal <a href="https://gist.github.com/bensu/e146fff87a67f41798ca">sample</a>:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(ns <span class="code-keyword">import</span>-names.core
(:<span class="code-keyword">import</span> [goog debug]))
(def debug goog.debug)</pre>
</div></div>CLJS-1271Missing warning when assigning namespaces via defDefectMinorOpenUnresolvedUnassignedSebastian BensusanSun, 17 May 2015 15:49:07 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next00<p>The example case is a bit complected. Besides importing a name that matches a def you are also assigning a google closure namespace to a local. This will likely cause problems on its own. We need more information.</p><p>We should check that <tt>:require</tt> ed and <tt>:import</tt> ed namespaces are not used as values and then warn about it.</p>Global Rank[CLJS-1238] Setting *main-cli-fn* when using :target :nodejs shouldn't be manditoryhttp://dev.clojure.org/jira/browse/CLJS-1238
ClojureScript<p>Currently, when you use :target :nodejs in the build options for ClojureScript, the resulting code requires you to set <tt>&#42;main-cli-fn&#42;</tt> to a function.</p>
<p>This prevents someone from writing a library that can be used by JavaScript developers because it forces code execution on <tt>require</tt>. It also makes writing a CLI tool that can be distributed using NPM less straightforward. I ran into this issue trying to create a Leiningen template for writing CLI tools that could be installed using <tt>npm install</tt> or <tt>npm link</tt>. I had a wrapper script to take care of the CLI use-case, and intended to write the ClojureScript module in a more library oriented way, but ran into issues. I could work around this by not using the wrapper script, but it got me thinking about the more general library issue.</p>
<p>I don't see any reason why you should be forced to set <tt>&#42;main-cli-fn&#42;</tt> and so I'm suggesting making it optional.</p>
<p>Attached is a patch that makes it optional but retains the check for whether the value it is set to is a function in the case where it is set.</p>
<p>This is my first time submitting a change to a project using a git patch and not a pull request, so let me know if I've made the patch wrong.</p>CLJS-1238Setting *main-cli-fn* when using :target :nodejs shouldn't be manditoryEnhancementMinorOpenUnresolvedUnassignedJeremy ShoemakerFri, 1 May 2015 19:25:42 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next22<p>I just noticed the priority defaulted to "Major". I don't know if I'd say it's major, so feel free to bump it down if that doesn't seem appropriate.</p><p>+1. </p>
<p>I was working on a clojurescript library and going to build it as a node library. Currently blocked by this.</p><p>Patch no longer applies.</p>Global RankPatchCode[CLJS-1237] ns-unmap doesn't work on refers from cljs.corehttp://dev.clojure.org/jira/browse/CLJS-1237
ClojureScript<p>In ClojureScript, using <tt>ns-unmap</tt> on a symbol from <tt>cljs.core</tt> doesn't exclude it from the current namespace. Note that both a function and a macro still exist, even after unmapping:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>To quit, type: :cljs/quit
cljs.user=&gt; (ns-unmap 'cljs.user 'when) ;; macro
true
cljs.user=&gt; (ns-unmap 'cljs.user 'not) ;; function
true
cljs.user=&gt; (when 1 2)
2
cljs.user=&gt; (not false)
true
</pre>
</div></div>
<p>This differs from the behavior of Clojure's <tt>ns-unmap</tt>. Note the appropriate errors when attempting to use unmapped symbols:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>Clojure 1.7.0-beta1
user=&gt; (ns-unmap 'user 'when) ;; macro
nil
user=&gt; (ns-unmap 'user 'not) ;; function
nil
user=&gt; (when 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: when in this context, compiling:(NO_SOURCE_PATH:11:1)
user=&gt; (not false)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: not in this context, compiling:(NO_SOURCE_PATH:12:1)
</pre>
</div></div>
<p>Somehow ClojureScript's <tt>ns-unmap</tt> needs to add the symbol to the current namespace's <tt>:excludes</tt> set. Note that the <tt>def</tt> special form does this already (after it displays a warning).</p>
<p>We have two solutions. 0001 extends the <tt>ns</tt> form's <tt>:merge</tt> behavior to support <tt>:excludes</tt>, and then uses this in <tt>ns-unmap</tt>. If the enhancement to <tt>ns</tt> isn't wanted, patch 0002 changes <tt>ns-unmap</tt> to update <tt>:excludes</tt> directly.</p>CLJS-1237ns-unmap doesn't work on refers from cljs.coreDefectMinorOpenUnresolvedUnassignedChouserns-unmapFri, 1 May 2015 16:01:36 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next02<p>The second patch is preferred. However it seems the second patch is too permissive. The <tt>:excludes</tt> logic should only be applied if the symbol identifies a core macro or fn.</p><p>The ns form's own :refer-clojure :exclude accepts arbitrary symbols and adds them to the namespace's :excludes set, which seems like the same permissiveness problem. Do you want a patch that addresses the permissiveness of both ns and ns-unmap in this ticket, or should such a patch go in a new ticket?</p><p>New ticket to fix the bug that <tt>:exclude</tt> doesn't check the symbol list for <tt>cljs.core</tt> declared vars, and an updated patch here please.</p>Global RankPatchCode[CLJS-1222] Sequence of a stateful transducer is producing the wrong answerhttp://dev.clojure.org/jira/browse/CLJS-1222
ClojureScript<p>I'm producing more than one element on the 1-arity of the transducer, and sequence is only considering the last one.</p>
<p>Here is the transducer and the tests that fail for sequence:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn sliding-window [n]
(fn [rf]
(let [a #js []]
(fn
([] (rf))
([result]
(loop [] ;; Here I'm emitting more than one element
(when (not-empty a)
(rf result (vec (js-&gt;clj a)))
(.shift a)
(recur))))
([result input]
(.push a input)
(<span class="code-keyword">if</span> (== n (.-length a))
(let [v (vec (js-&gt;clj a))]
(.shift a)
(rf result v))
result))))))
;;This test fails! =(
(deftest sliding-window-in-a-sequence
(is (= [[5 4 3]
[4 3 2]
[3 2 1]
[2 1]
[1]]
(sequence (sliding-window 3) [5 4 3 2 1])))
(is (= [[2 1]
[1]]
(sequence (sliding-window 3) [2 1]))))</pre>
</div></div>OSX 10.10.3, java 1.8.0-ea-b124CLJS-1222Sequence of a stateful transducer is producing the wrong answerDefectMinorOpenUnresolvedUnassignedLucas CavalcantibugcljscollectionsFri, 24 Apr 2015 10:16:45 -0500Tue, 8 Nov 2016 14:14:34 -06001.7.145Next02<p>I could make it work by recurring on the result. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">([result]
(loop [res result]
(<span class="code-keyword">if</span> (not-empty a)
(let [v (vec (js-&gt;clj a))]
(.shift a)
(recur (rf res v)))
res)))</pre>
</div></div>
<p>even so it's weird that the previous version behaves differently on core.async and sequences in cljs and clj</p><p>Please demonstrate the problem without core.async. Thanks.</p><p>Hi,</p>
<p>the last test I posted on the ticket, fails in cljs, but not in clj:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;;This test fails! =(
(deftest sliding-window-in-a-sequence
(is (= [[5 4 3]
[4 3 2]
[3 2 1]
[2 1]
[1]]
(sequence (sliding-window 3) [5 4 3 2 1])))
(is (= [[2 1]
[1]]
(sequence (sliding-window 3) [2 1]))))</pre>
</div></div><p>I've removed the core.async bits from the description to clarify the issue.</p><p>The implementation of <tt>sliding-window</tt> above does not appear to be correct, it doesn't return the result. This ticket needs more information.</p><p>As I said on <a href="http://dev.clojure.org/jira/browse/CLJS-1222?focusedCommentId=38620&amp;page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-38620">http://dev.clojure.org/jira/browse/CLJS-1222?focusedCommentId=38620&amp;page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-38620</a></p>
<p>changing the 1-arity of the <tt>sliding-window</tt> to that fixes the transducer.</p>
<p>The point of this ticket now is that the behavior of the same (wrong) transducer in clj (both core.async and sequence) and cljs (core.async) is different than cljs sequence.</p>Global Rank[CLJS-1207] Emit a warning if multiple resources found for a ClojureScript namespacehttp://dev.clojure.org/jira/browse/CLJS-1207
ClojureScript<p>We should emit a simple warning if a namespace doesn't not appear to be unique on the classpath.</p>CLJS-1207Emit a warning if multiple resources found for a ClojureScript namespaceEnhancementMinorOpenUnresolvedUnassignedDavid NolenWed, 15 Apr 2015 14:21:21 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next02Global Rank[CLJS-1174] Simple warning if a namespace with dashes not found but a file path with dashes existshttp://dev.clojure.org/jira/browse/CLJS-1174
ClojureScriptCLJS-1174Simple warning if a namespace with dashes not found but a file path with dashes existsEnhancementMinorOpenUnresolvedUnassignedDavid NoleneasyFri, 27 Mar 2015 09:42:43 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next00Global Rank[CLJS-1159] compiled files with warnings that otherwise don't need recompilation will not emit warnings on the next compilehttp://dev.clojure.org/jira/browse/CLJS-1159
ClojureScript<p>The aggressive caching approach is odds with warning visibility. It probably makes sense for a compiled file with warnings to always return <tt>true</tt> for <tt>requires-compilation?</tt>.</p>CLJS-1159compiled files with warnings that otherwise don't need recompilation will not emit warnings on the next compileDefectMinorOpenUnresolvedUnassignedDavid NolenMon, 23 Mar 2015 06:05:42 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next11Global Rank[CLJS-1139] Repeated applications of `ns` form at the REPL are not additivehttp://dev.clojure.org/jira/browse/CLJS-1139
ClojureScript<p>In a Clojure REPL, it is possible to declare the same namespace again, without existing namespaces aliases being altered or removed:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">user=&gt; (ns my-test-ns.core (:require [clojure.string :as string]))
nil
my-test-ns.core=&gt; (def a string/blank?)
#'my-test-ns.core/a
my-test-ns.core=&gt; (ns my-test-ns.core)
nil
my-test-ns.core=&gt; (def a string/blank?)
#'my-test-ns.core/a
my-test-ns.core=&gt;</pre>
</div></div>
<p>ClojureScript REPLs do not behave in the same way:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (ns my-test-ns.core (:require [clojure.string :as string]))
<span class="code-keyword">true</span>
ClojureScript:my-test-ns.core&gt; (def a string/blank?)
#&lt;function clojure$string$blank_QMARK_(s){
<span class="code-keyword">return</span> goog.string.isEmptySafe(s);
}&gt;
ClojureScript:my-test-ns.core&gt; (ns my-test-ns.core)
nil
ClojureScript:my-test-ns.core&gt; (def a string/blank?)
WARNING: No such namespace: string, could not locate string.cljs at line 1 &lt;cljs repl&gt;
WARNING: Use of undeclared Var string/blank? at line 1 &lt;cljs repl&gt;
repl:13
<span class="code-keyword">throw</span> e__3919__auto__;
^
ReferenceError: string is not defined
at repl:1:109
at repl:9:3
at repl:14:4
at <span class="code-object">Object</span>.exports.runInThisContext (vm.js:74:17)
at Domain.&lt;anonymous&gt; ([stdin]:41:34)
at Domain.run (domain.js:197:16)
at Socket.&lt;anonymous&gt; ([stdin]:40:25)
at Socket.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:163:16)
at Socket.Readable.push (_stream_readable.js:126:10)
ClojureScript:my-test-ns.core&gt;</pre>
</div></div>Quick start guide with Node REPLCLJS-1139Repeated applications of `ns` form at the REPL are not additiveDefectMinorOpenUnresolvedUnassignedMichael GriffithsTue, 17 Mar 2015 18:17:53 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next00Global Rank[CLJS-1136] Initial require fails to fully load added symbolshttp://dev.clojure.org/jira/browse/CLJS-1136
ClojureScript<p>In the Quick Start, a portion runs the user through adding a symbol (a function named <tt>foo</tt>) and then requiring the namespace and using that symbol. I'm finding that <tt>require</tt> fails and that I need to add the <tt>:reload</tt> directive.</p>
<p>To reproduce:</p>
<ol>
<li>Run through the Quick Start up through the browser REPL section.</li>
<li>Set <tt>src/hello_world/core.cljs</tt> so that it does not have the <tt>foo</tt> function defined.</li>
<li>Remove the <tt>out</tt> directory: <tt>rm -rf out</tt></li>
<li>Start up the REPL: <tt>rlwrap java -cp cljs.jar:src clojure.main repl.clj</tt></li>
<li>Connect Safari by going to <tt><a href="http://localhost:9000">http://localhost:9000</a></tt></li>
<li>Show the error console in Safari. (You'll see <tt>Hello world</tt>.)</li>
<li>Run <tt>tail -f out/watch.log</tt></li>
<li>Add the <tt>foo</tt> function that adds <tt>a b</tt> to <tt>src/hello_world/core.cljs</tt> and save it.</li>
<li>Observe that <tt>watch.log</tt> reflects recompilation</li>
<li>Do {{ (require '<span class="error">&#91;hello-world.core :as hello&#93;</span>) }}</li>
<li>Do {{ (hello/foo 2 3) }}</li>
</ol>
<p>At this point you will get:<br/>
<tt>TypeError: undefined is not an object (evaluating 'hello_world.core.foo.call')</tt></p>
<p>But:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (ns-interns 'hello-world.core)
{foo #'hello-world.core/foo, conn #'hello-world.core/conn}
ClojureScript:cljs.user&gt; (source hello/foo)
(defn foo [a b]
(+ a b))
nil</pre>
</div></div>
<p>Now, if you <tt>:reload</tt></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (require '[hello-world.core :as hello] :reload)
nil
ClojureScript:cljs.user&gt; (hello/foo 2 3)
5</pre>
</div></div>Quick Start Browser REPL (OS X / Safari)CLJS-1136Initial require fails to fully load added symbolsDefectMinorOpenUnresolvedUnassignedMike FikesTue, 17 Mar 2015 11:23:36 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next01<p>Prior to step 8:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (ns-interns 'hello-world.core)
{}</pre>
</div></div>
<p>Between steps 9 and 10:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (ns-interns 'hello-world.core)
{foo #'hello-world.core/foo, conn #'hello-world.core/conn}</pre>
</div></div>
<p>My guess: Watching is causing symbols to be interned, but not usable, and this is interfering with <tt>require</tt> forcing you to include <tt>:reload</tt>.</p><p>I'm not sure that this is actually an issue, the browser has already required the namespace, it's the entry point. Thus you really do need a <tt>:reload</tt>. But the reason you see interned symbols is that the watch process shares the compilation environment with the REPL. It may be the case that with the dramatically improved REPLs the watch option becomes entirely unnecessary and counterintuitive, let's see how it goes.</p>Global Rank[CLJS-1134] Lift protocols from cljs.closure into cljs.protocols nshttp://dev.clojure.org/jira/browse/CLJS-1134
ClojureScript<p>This is task towards presenting a stable API to users without reaching into the implementation namespaces.</p>CLJS-1134Lift protocols from cljs.closure into cljs.protocols nsTaskMinorOpenUnresolvedUnassignedDavid NolenTue, 17 Mar 2015 09:27:03 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next00Global Rank[CLJS-1133] REPL require results in warnings to be emitted twicehttp://dev.clojure.org/jira/browse/CLJS-1133
ClojureScript<p>Run through the Quick Start and go down through to the Browser REPL portion (<a href="https://github.com/clojure/clojurescript/wiki/Quick-Start#browser-repl">https://github.com/clojure/clojurescript/wiki/Quick-Start#browser-repl</a>), but exclude the <tt>:watch</tt> option from <tt>repl.clj</tt>.</p>
<p>Then further down, where the new symbol is introduced</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">;; ADDED
(defn foo [a b]
(+ a b))</pre>
</div></div>
<p>instead cause some duplicate symbols to be introduced in order to provoke compiler warnings:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(def a 1)
(def a 1)
(defn foo [a b]
(+ a b))
(defn foo [a b]
(+ a b))</pre>
</div></div>
<p>Then evaluate the <tt>require</tt> statement in the tutorial and observe that the warnings are emitted twice:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (require '[hello-world.core :as hello])
WARNING: a at line 11 is being replaced at line 12 /Users/mfikes/Desktop/hello_world/src/hello_world/core.cljs
WARNING: foo at line 14 is being replaced at line 16 /Users/mfikes/Desktop/hello_world/src/hello_world/core.cljs
WARNING: a at line 11 is being replaced at line 12 /Users/mfikes/Desktop/hello_world/src/hello_world/core.cljs
WARNING: foo at line 14 is being replaced at line 16 /Users/mfikes/Desktop/hello_world/src/hello_world/core.cljs
nil</pre>
</div></div> Quick Start Browser REPL with :watch offCLJS-1133REPL require results in warnings to be emitted twiceDefectMinorOpenUnresolvedUnassignedMike FikesTue, 17 Mar 2015 09:05:09 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next00Global Rank[CLJS-1129] :modules tutorial for wikihttp://dev.clojure.org/jira/browse/CLJS-1129
ClojureScript<p>The documentation is nice but something that walks people through the steps would be nicer.</p>CLJS-1129:modules tutorial for wikiTaskMinorOpenUnresolvedUnassignedDavid NolendocumentationnewbieMon, 16 Mar 2015 11:27:47 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next00Global Rank[CLJS-1127] validate compiled file written to diskhttp://dev.clojure.org/jira/browse/CLJS-1127
ClojureScript<p>If we validate the file written to disk then we can catch common error of running multiple build processes and abort.</p>CLJS-1127validate compiled file written to diskEnhancementMinorOpenUnresolvedUnassignedDavid NolenMon, 16 Mar 2015 09:34:39 -0500Tue, 8 Nov 2016 14:14:36 -06001.7.145Next00Global Rank[CLJS-1125] Simple corrupted compiled file detectionhttp://dev.clojure.org/jira/browse/CLJS-1125
ClojureScript<p>We should include a line at the end of the file that we check for to determine that the file was not corrupted due to either an incomplete write or a clobbered write. It should be be the SHA of the ClojureScript source it was generated from.</p>CLJS-1125Simple corrupted compiled file detectionEnhancementMinorOpenUnresolvedUnassignedDavid NolenMon, 16 Mar 2015 07:40:25 -0500Tue, 8 Nov 2016 14:14:36 -06001.7.145Next01Global Rank[CLJS-1070] top-level boolean inference does not workhttp://dev.clojure.org/jira/browse/CLJS-1070
ClojureScript<p>Problem for using boolean Closure defines</p>CLJS-1070top-level boolean inference does not workDefectMinorOpenUnresolvedUnassignedDavid NolenSat, 28 Feb 2015 12:16:08 -0600Tue, 8 Nov 2016 14:14:36 -06001.7.145Next00<p>I am unsure if this is the same issue, but forms like <tt>^boolean (js/isFinite n)</tt> also do not seem to analyze correctly: <tt>if</tt>, <tt>and</tt>, and <tt>or</tt> will still emit a call to <tt>truth_</tt>.</p>Global Rank[CLJS-871] .-default property access returns nilhttp://dev.clojure.org/jira/browse/CLJS-871
ClojureScript<p>Types defined with deftype/defrecord which have a <tt>default</tt> field will incorrectly return <tt>nil</tt> with property access. The following example will return <tt>nil</tt>.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(deftype Foo [<span class="code-keyword">default</span>])
(let [foo (Foo. <span class="code-quote">"bar"</span>)]
(.-<span class="code-keyword">default</span> foo))</pre>
</div></div>CLJS-871.-default property access returns nilDefectMinorOpenUnresolvedUnassignedJoel HoldbrooksSat, 11 Oct 2014 22:54:59 -0500Tue, 8 Nov 2016 14:14:36 -06001.7.145Next11<p>Patch attached. I should point out that I had to borrow js-reserved from the compiler namespace and the warning message provided hard codes the munged symbol information instead of reusing the compiler's munge fn.</p><p>For the sake of history, I should provide more context to this patch (I'm unable to edit the issue title for some reason). It isn't just <tt>.-default</tt> it is any field name that is also a JavaScript identifier (eg. <tt>public</tt>, <tt>private</tt>, <tt>if</tt>).</p><p>Please lift <tt>js-reserved</tt> and any helpers like <tt>munge</tt> into the shared namespace <tt>cljs.util</tt> so that logic an be shared and hard coding avoided. Thanks.</p><p>Are you sure, David? That might make this patch a bit more noisy. If it's not a problem I'm happy to do it.</p><p>I'm sure, I'd like to avoid this kind of code duping. Cleaner in the end and better moving forward.</p><p>Updated to use new refactorings</p><p>The warning is not desirable. Instead we should just munge and ensure property access always works.</p>Global RankPatchCode and Test[CLJS-794] RegExp flags are being dropped by `string/replace`http://dev.clojure.org/jira/browse/CLJS-794
ClojureScript<p>`clojure.string/replace` accepts either a string or pattern argument to match against.</p>
<p>For pattern arguments, the current implementation discards the original RegExp and creates a new one:<br/>
`(.replace s (js/RegExp. (.-source match) "g") replacement)`</p>
<p>This is killing any flags on the original pattern (case insensitivity, for example). As a result, things like `(str/replace "Foo" #"(?i)foo" "bar")` currently fail. The result is "Foo", it should be "bar".</p>
<p>Can I submit a patch that'll check for and preserve other (i/m/y) flags?</p>
<p>Thanks</p>CLJS-794RegExp flags are being dropped by `string/replace`DefectMinorOpenUnresolvedUnassignedPeter TaoussanisWed, 9 Apr 2014 06:33:59 -0500Tue, 8 Nov 2016 14:14:36 -06001.7.145Next23<p>A patch is welcome for this. Thanks.</p><p>This appears to be identical to <a href="http://dev.clojure.org/jira/browse/CLJS-485" title="clojure.string/replace ignores regex flags">CLJS-485</a>, which has a patch (by someone who hasn't signed the CLA yet).</p><p>This patch changes string/replace-all to respect flags that were set on regexp passed as an argument.</p>Global Rank[CLJS-485] clojure.string/replace ignores regex flagshttp://dev.clojure.org/jira/browse/CLJS-485
ClojureScript<p>The replace function in namespace clojure.string ignores regex flag provided in the match pattern. For example: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>CLJS</b></div><div class="codeContent panelContent">
<pre class="code-java">clojure.string/replace <span class="code-quote">"I am NOT matched"</span> #<span class="code-quote">"(?i)not "</span> "")
=&gt; <span class="code-quote">"I am NOT matched"</span></pre>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>CLJ</b></div><div class="codeContent panelContent">
<pre class="code-java">clojure.string/replace <span class="code-quote">"I am NOT matched"</span> #<span class="code-quote">"(?i)not "</span> "")
=&gt; <span class="code-quote">"I am matched"</span></pre>
</div></div>
<p>The attached patch fixes this by parsing the m and i flags, if set, from the match object, instead of explicitly setting only "g".</p>CLJS-485clojure.string/replace ignores regex flagsDefectMinorOpenUnresolvedUnassignedEsa VirtanenbugpatchtestTue, 12 Mar 2013 07:27:06 -0500Tue, 8 Nov 2016 14:14:36 -06001.7.145Next35<p>I can confirm the bug. The attached patch applies cleanly, and works as expected.</p>
<p>Esa, sorry for the long delay (this one must have slipped through the cracks)! <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/sad.gif" height="20" width="20" align="absmiddle" alt="" border="0"/> Could you please submit a contributor's agreement, so that your patch can be merged? More info is here:</p>
<p><a href="http://clojure.org/contributing">http://clojure.org/contributing</a></p><p>I got bit by this bug. Working on figuring out if I can sign that agreement.</p><p>This is a duplicate of <a href="http://dev.clojure.org/jira/browse/CLJS-794" title="RegExp flags are being dropped by `string/replace`">CLJS-794</a>.</p><p>This patch changes string/replace-all to respect flags that were set on regexp passed as an argument.</p>
<p>I originally attached this to <a href="http://dev.clojure.org/jira/browse/CLJS-794" title="RegExp flags are being dropped by `string/replace`">CLJS-794</a> and then noticed there was this older issue. I was unable to figure out how to edit at ticket to mark the patch as having "Code and Test" so I'm adding it to this issue instead.</p>
<p>I've signed a contributors agreement.</p><p>There is a "sticky" flag <tt>y</tt> that could be conveyed.</p>
<p><a href="http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-regexp.prototype.sticky">http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-regexp.prototype.sticky</a></p><p>Reading a bit more about it and looks like both 'u' and 'y' are newly supported in ECMA6. Is there a way to write tests that exercise this functionality? I've got changes locally to get support of 'y' but felt the need to write a test for it (as its a bit more complicated than simply looking for a flag) and am hung up on having EMCA6 support while running the tests.</p>
<p>I'm actually wondering if having 'u' and 'y' in there is a bit premature. Any guidance on whether adding code for 'u' and 'y' should be done (or removing 'u' from my patch) or testing ClojureScript with ECMAScript 6 support?</p><p>One thought: Whatever this is exercising passes on recent versions of V8, JavaScriptCore, SpiderMonkey, Nashorn, and ChakraCore: <a href="https://github.com/clojure/clojurescript/blob/628d957f3ecabf8d26d57665abdef3dea765151e/src/test/cljs/cljs/core_test.cljs#L1472">https://github.com/clojure/clojurescript/blob/628d957f3ecabf8d26d57665abdef3dea765151e/src/test/cljs/cljs/core_test.cljs#L1472</a></p>
<p>It does seem tricky to write a robust RegExp clone implementation, and if you do some googling you see people dealing with <tt>u</tt> and <tt>y</tt> as special cases. The patch seemed OK to me with respect to this, but I'm not a JavaScript expert.</p>Global RankPatchCode and Test[CLJS-434] ClojureScript compiler prepends "self__" to defmulti forms when metadata in form of ^:field.http://dev.clojure.org/jira/browse/CLJS-434
ClojureScript<p>Using the def form, with the specific metadata ^:field causes the cljs compiler<br/>
to prepend "self__" to the output js form.</p>
<p>The browser (latest chrome/firefox) does not recognize "self__".</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Test Case: Tested against master: 5ac1503
-------------
(ns test-def)
(def ^:foo e identity)
e
; test_def.e = cljs.core.identity;
; test_def.e;
(def ^:field f identity)
f
; test_def.f = cljs.core.identity;
; self__.test_def.f;
; Uncaught ReferenceError: self__ is not defined</pre>
</div></div>
<p><a href="https://gist.github.com/4185793">https://gist.github.com/4185793</a></p>Mac OS X (10.7), java version &quot;1.6.0_37&quot;, leiningen 2 preview 10, cljsbuild 0.2.9.
<br/>
clojure/clojurescript master 01 December 2012 - 5ac1503CLJS-434ClojureScript compiler prepends "self__" to defmulti forms when metadata in form of ^:field.DefectMinorOpenUnresolvedUnassignedAndrew McveighbugSat, 1 Dec 2012 17:34:52 -0600Tue, 8 Nov 2016 14:14:36 -06001.7.145Next03<p>code tags</p><p>This one is a bit annoying. We should probably use namespaced keywords internally.</p>Global Rank[CLJS-375] loop doesn't seem to preserve tag information as evidenced by extra cljs.core.truth_ callshttp://dev.clojure.org/jira/browse/CLJS-375
ClojureScriptCLJS-375loop doesn't seem to preserve tag information as evidenced by extra cljs.core.truth_ callsDefectMinorOpenUnresolvedUnassignedDavid NolenThu, 6 Sep 2012 20:33:14 -0500Tue, 8 Nov 2016 14:14:36 -06001.7.145Next01Global Rank[CLJS-349] cljs.compiler: No defmethod for emit-constant clojure.lang.LazySeqhttp://dev.clojure.org/jira/browse/CLJS-349
ClojureScript<p>The cljs compiler errors when trying to emit-constant for a clojure.lang.LazySeq.</p>
<p>Example : <a href="https://www.refheap.com/paste/3901">https://www.refheap.com/paste/3901</a></p>
<p>Here syms is defined as a LazySeq on line 3, then on line 7 it is quoted. The error is included in the refheap.</p>
<p>Emitting a cljs.core.list for this type seems to solve the issue.</p>CLJS-349cljs.compiler: No defmethod for emit-constant clojure.lang.LazySeqDefectMinorOpenUnresolvedUnassignedJulien FantinMon, 30 Jul 2012 18:06:31 -0500Tue, 8 Nov 2016 14:14:37 -06001.7.145Next01<p>Can you identify precisely where a LazySeq is getting emitted here? A LazySeq is not literal so this seems like a bug in the macro to me. I could be wrong. Thanks!</p><p>The lazy seq seems to be introduced on line 7, the '~syms form</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">`(let [mappings# (into {} (map-indexed #(identity [%2 %1]) '~syms))</pre>
</div></div>
<p>Clojure allows lazy-seqs to be embedded: <a href="https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L4538">https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L4538</a></p>
<p>As an aside: The relevant protocol is not literality, but the print-dup multimethod. Do / Should we have print-dup in CLJS?</p><p>Attached patch 0001 doesn't add a case for LazySeq, but folds two cases for PersistentList and Cons into one for ISeq.</p><p>This approach seems acceptable but this is an old patch can we update for master?</p>Global Rank[CLJS-1128] Describe internationalization strategies via Google Closure on the wikihttp://dev.clojure.org/jira/browse/CLJS-1128
ClojureScript<p>This can be done via Google Closure defines or via pulling a specific locale. A page should document how this can be done.</p>CLJS-1128Describe internationalization strategies via Google Closure on the wikiTaskMinorOpenUnresolvedUnassignedDavid NolendocumentationnewbieMon, 16 Mar 2015 10:47:16 -0500Tue, 8 Nov 2016 14:14:35 -06001.7.145Next01Global Rank[CLJS-1846] Range issueshttp://dev.clojure.org/jira/browse/CLJS-1846
ClojureScript<p><b>Problem</b><br/>
There are a number of bugs with Range which occur when the step size is 0 or where negative.</p>
<p><b>Examples</b></p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>cljs.user=&gt; (count (range 10 0 0))
-Infinity ;Expect Infinity
cljs.user=&gt; (nth (range 10 0 -1) -1)
11 ; Expected IndexOutOfBounds
cljs.user=&gt; (take 5 (sequence identity (range 0 10 0)))
() ; Expected (0 0 0 0 0)
cljs.user=&gt; (into [] (take 5) (range 0 10 0))
[] ; Expected [0 0 0 0 0]
</pre>
</div></div>CLJS-1846Range issuesDefectMinorOpenUnresolvedUnassignedThomas MulvaneyThu, 10 Nov 2016 08:01:51 -0600Tue, 15 Nov 2016 08:24:45 -060001<p>This patch is headed in the right direction but it needs to be more vigilant about performance. I'm more than happy to talk it over via IRC or Slack. Thanks!</p><p>Updated patch with performance tweaks.</p>
<ul>
<li>Added the ^boolean annotation to the `some-range?` helper.</li>
<li>Removed calls to methods of Range where possible.</li>
<li>Improved 2-arity reduces performance over master significantly by replacing the call to ci-reduce.</li>
</ul>
Global RankPatchCode and Test[CLJS-1852] explain-data problems don't provide resolved symbols under :predhttp://dev.clojure.org/jira/browse/CLJS-1852
ClojureScript<p>Same as <a href="http://dev.clojure.org/jira/browse/CLJ-2059">http://dev.clojure.org/jira/browse/CLJ-2059</a> which has a patch.</p>CLJS-1852explain-data problems don't provide resolved symbols under :predDefectMinorOpenUnresolvedUnassignedDavid NolenTue, 15 Nov 2016 14:17:41 -0600Tue, 15 Nov 2016 14:17:41 -06001.9.29300Global Rank[CLJS-1853] Docstrings are included in compiled outputhttp://dev.clojure.org/jira/browse/CLJS-1853
ClojureScript<p>Looking at code compiled with 'advanced':</p>
<p>$cljs$core$cst$0sym$0_STAR_print_DASH_base_STAR_$$, "target/release-browser/cljs/pprint.cljs", 13, 1, !0, 672, 675, $cljs$core$List$EMPTY$$, "The base to use for printing integers and rationals.", $cljs$core$truth_$$($cljs$pprint$<em>STAR_print_base_STAR</em>$$) ? $cljs$pprint$<em>STAR_print_base_STAR</em>$$.$cljs$lang$test$ : null]))]);</p>
<p>...</p>
<p>$cljs$core$cst$0sym$0cljs$0pprint$$, $cljs$core$cst$0sym$0_STAR_print_DASH_right_DASH_margin_STAR_$$, "target/release-browser/cljs/pprint.cljs", 22, 1, !0, 625, 630, $cljs$core$List$EMPTY$$, "Pretty printing will try to avoid anything going beyond this column.\nSet it to nil to have pprint let the line be arbitrarily long. This will ignore all\nnon-mandatory newlines.", $cljs$core$truth_$$($cljs$pprint$<em>STAR_print_right_margin_STAR</em>$$) ? $cljs$pprint$<em>STAR_print_right_margin_STAR</em>$$.$cljs$lang$test$ : </p>
<p>It looks like docstrings aren't stripped from dynamic vars, only from functions.</p>
<p>This is a bit of a waste of space...</p>CLJS-1853Docstrings are included in compiled outputDefectMinorOpenUnresolvedUnassignedRichard NewmanTue, 15 Nov 2016 15:22:01 -0600Tue, 15 Nov 2016 15:22:01 -06001.9.29300Global Rank[CLJS-1854] Self-host: Reload ns with consthttp://dev.clojure.org/jira/browse/CLJS-1854
ClojureScript<p>Bootstrapped ClojureScript fails to allow you to reload a namespace containing a constant.</p>
<p>To reproduce, evaluate the following forms in a REPL:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(require 'cljs.js)
(def st (cljs.js/empty-state))
(cljs.js/eval st
'(require (quote foo.core))
{:context :expr
:eval cljs.js/js-eval
:load (fn [_ cb]
(cb {:lang :clj
:source <span class="code-quote">"(ns foo.core) (def ^:<span class="code-keyword">const</span> x 1)"</span>}))}
prn)
(cljs.js/eval st
'(require (quote foo.core) :reload)
{:context :expr
:eval cljs.js/js-eval
:load (fn [_ cb]
(cb {:lang :clj
:source <span class="code-quote">"(ns foo.core) (def ^:<span class="code-keyword">const</span> x 2)"</span>}))}
prn)</pre>
</div></div>
<p>The expectation is that the <tt>:reload</tt> directive in the last <tt>require</tt> will allow the namespace to be loaded with the const <tt>def</tt> being re-defined.</p>
<p>Instead, you get the following in the <tt>eval</tt> callback:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">{:error #error {:message <span class="code-quote">"Could not eval foo.core"</span>, :data {:tag :cljs/analysis-error}, :cause #error {:message <span class="code-quote">"Can't redefine a constant at line 1 "</span>, :data {:file nil, :line 1, :column 15, :tag :cljs/analysis-error}}}}</pre>
</div></div>
<p>Note: This has probably been a defect in bootstrapped ClojureScript for quite a while (maybe forever). In particular, it is not a regression introduced with the new <tt>require</tt> capability (<a href="http://dev.clojure.org/jira/browse/CLJS-1346" title="Support require outside of ns "><del>CLJS-1346</del></a>). </p>
<p>FWIW, Planck has been working around this (and violating public API), manipulating <tt>cljs.js/&#42;loaded&#42;</tt> via its <tt>require</tt> REPL special, essentially purging portions of the analysis cache when reloading: <a href="https://github.com/mfikes/planck/blob/1.17/planck-cljs/src/planck/repl.cljs#L329-L348">https://github.com/mfikes/planck/blob/1.17/planck-cljs/src/planck/repl.cljs#L329-L348</a> </p>CLJS-1854Self-host: Reload ns with constDefectMinorOpenUnresolvedUnassignedMike FikesbootstrapWed, 16 Nov 2016 19:55:15 -0600Wed, 16 Nov 2016 20:21:41 -060001Global Rank[CLJS-901] Protocolize compiler access to the file systemhttp://dev.clojure.org/jira/browse/CLJS-901
ClojureScript<p>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.</p>CLJS-901Protocolize compiler access to the file systemTaskMinorOpenUnresolvedUnassignedDavid NolenWed, 3 Dec 2014 07:42:23 -0600Fri, 18 Nov 2016 19:49:51 -060037<p>This and some other issues opened recently (<a href="http://dev.clojure.org/jira/browse/CLJS-900" title="Parameterize caching strategy">CLJS-900</a>, <a href="http://dev.clojure.org/jira/browse/CLJS-851" title="simplify :none script inclusion if :main supplied"><del>CLJS-851</del></a>, <a href="http://dev.clojure.org/jira/browse/CLJS-899" title="AOT cache core.cljs analysis"><del>CLJS-899</del></a>, ...) have some overlap with what I have done in shadow-build <span class="error">&#91;1&#93;</span>. Memory based builds are actually already possible cause it will only touch the disk when asked to, although the API could use some cleanup.</p>
<p>Anyways, might be worthwhile to coordinate these efforts to make CLJS more accessible for everyone.</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://github.com/thheller/shadow-build">https://github.com/thheller/shadow-build</a></p><p>I too think it would be totally awesome to have builds based on sources from disparate places.</p>
<p>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.</p>
<p>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.</p>
<p>This whole idea is inspired by boot's FileSets, which work basically the same but can't have the "it fits in memory" assumption.</p>Global Rank[CLJS-1615] Inlining truth checks can lead to better optimisation resultshttp://dev.clojure.org/jira/browse/CLJS-1615
ClojureScript<p>I had a situation when DCE was (naively) expected but didn't happen (in :advanced compilation mode). I did some exploration and discovered that inlined truth check code is better understood by Closure Compiler and leads to expected optimisation (for some reasons).</p>
<p>I believe understanding this behaviour and exploiting it where desirable could lead to more predictable code generation without resorting to using cljs type hints.</p>CLJS-1615Inlining truth checks can lead to better optimisation resultsEnhancementMinorOpenUnresolvedUnassignedAntonin HildebrandMon, 4 Apr 2016 14:46:06 -0500Fri, 8 Apr 2016 14:00:20 -050012<p>The backstory as posted to #cljs-dev in Slack:</p>
<p>When @domkm requested proper dead code elimination in cljs-devtools, I got burnt by the need to explicitly specify `(if ^boolean js/goog.DEBUG …)` hint to get `:closure-defines` working under :advanced build<span class="error">&#91;1&#93;</span>. It was unexpected to me that closure compiler cannot see that optimization and does not inline truth test for js/goog.DEBUG “constant”. So I started poking around and found a way how to aggressively inline checked truth checks in a compatible way (I believe). I also believe this could potentially open optimizations in other places. I think we should explore `@nosideeffects` annotation<span class="error">&#91;2&#93;</span> and tag core functions where appropriate.</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://github.com/binaryage/cljs-devtools/releases/tag/v0.5.3">https://github.com/binaryage/cljs-devtools/releases/tag/v0.5.3</a><br/>
<span class="error">&#91;2&#93;</span> <a href="https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en#tag-nosideeffects">https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en#tag-nosideeffects</a></p><p>`@nosideeffects` should only be relevant for extern files where the compiler cannot see the implementation and know if the function is pure. Normally the compiler just analyzes the function to see if it side-effects.</p>
<p>This may be a performance win as well: it looks like advanced compile will unwrap the function expression entirely in some cases (both expression and statement contexts), so no more megamorphic calls to truth_ or even function object allocations.</p>
<p>However, I don't think there's a <em>guarantee</em> that the closure compiler will always understand enough to remove the need for the ^boolean hint for defines in all cases.</p>Global RankPatchCode and Test[CLJS-1859] Comparing a map and a record with = produces different results based on argument order http://dev.clojure.org/jira/browse/CLJS-1859
ClojureScript<p>The result of comparing a map and a record is different based on the order of the arguments to <tt>=</tt>: </p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>To quit, type: :cljs/quit
cljs.user=&gt; (defrecord R [])
cljs.user/R
cljs.user=&gt; (= {} (R.))
true
cljs.user=&gt; (= (R.) {})
false
</pre>
</div></div>
<p>The result is the same for the code above with tags <tt>r1.7.228</tt>, <tt>r1.8.34</tt> and <tt>1.9.293</tt>.</p>
<p>This seems to be rooted in the fact that when a map is the first argument, the function used to make the comparison is the implementation of <tt>equiv</tt> from the map. But when a record is the first argument the implementation used is the one from the record, which checks if the types of both arguments are equal. </p>
<p>In Clojure JVM the implementation of <tt>equiv</tt> in <tt>clojure.lang.APersistentMap</tt> checks for the marker interface <tt>clojure.lang.MapEquivalence</tt>, which avoids this situation.</p>
Mac OS X
<br/>
V8
<br/>
java version &quot;1.8.0_73&quot;
<br/>
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
<br/>
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)CLJS-1859Comparing a map and a record with = produces different results based on argument order DefectMinorOpenUnresolvedUnassignedJuan FacorroWed, 23 Nov 2016 16:13:40 -0600Wed, 23 Nov 2016 16:14:47 -06001.9.2931.9.29300Global Rank[CLJS-1862] allow NodeJS's NODE_MODULES to be set as a REPL optionhttp://dev.clojure.org/jira/browse/CLJS-1862
ClojureScript<p>The NodeJS REPL that ships with ClojureScript seems to assume that all NodeJS modules are installed globally, or that node's NODE_PATH environment variable is set for the process that starts the REPL (e.g. CIDER). Allowing this to be set as a REPL option make it possible for modules to be installed and made available to the REPL by build tooling, eliminating manual steps by the user and improving repeatability. </p>CLJS-1862allow NodeJS's NODE_MODULES to be set as a REPL optionEnhancementMinorOpenUnresolvedUnassignedMarc DayanodejsreplMon, 28 Nov 2016 14:13:56 -0600Tue, 29 Nov 2016 14:02:45 -06001.9.29301<p>Thanks. Have you submitted your Clojure CA yet?</p><p>It has just been filed.</p>Global RankPatchCode[CLJS-1863] :reload/:reload-all issue with .cljc runtime/macro nseshttp://dev.clojure.org/jira/browse/CLJS-1863
ClojureScript<p>Brandon Bloom discovered an issue where a ns that is used both from runtime and for macros (where the macros are self-required) won't respect `(require ... :reload/:reload-all)`.</p>CLJS-1863:reload/:reload-all issue with .cljc runtime/macro nsesDefectMinorOpenUnresolvedUnassignedDavid NolenTue, 29 Nov 2016 15:42:28 -0600Tue, 29 Nov 2016 15:59:41 -06001.9.29300<p>Whatever we do needs to be copied over into a bootstrapped, but that's a separate issue.</p>Global Rank[CLJS-1864] timestamped source maps broken with Nodehttp://dev.clojure.org/jira/browse/CLJS-1864
ClojureScript<p>I'm using Figwheel with Node, and noticed a bug with timestamped source maps. When the <tt>:source-map-timestamp</tt> compiler flag is set, the <tt>sourceMappingURL</tt> is set to <tt>source.js.map?timestamp</tt>.</p>
<p>This works fine in the browser, but breaks in Node where files are loaded from the filesystem. It looks like a simple workaround would be to check if <tt>:target</tt> is <tt>:node</tt> and output something like <tt>source.js.timestamp.map</tt> instead, and use it directly as the value of <tt>sourceMappingURL</tt>.</p>
<p>Here's a change I made locally in <tt>cljs.compiler/emit-source-map</tt> that allows source maps to be resolved on Node when using timestamps:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>emit-source-map</b></div><div class="codeContent panelContent">
<pre class="code-java">(defn emit-source-map [src dest sm-data opts]
(let [timestamp (<span class="code-object">System</span>/currentTimeMillis)
filename (str (.getPath ^File dest)
(when (and
(<span class="code-keyword">true</span>? (:source-map-timestamp opts))
(= (:target opts) :nodejs))
(str <span class="code-quote">"."</span> timestamp))
<span class="code-quote">".map"</span>)
sm-file (io/file filename)]
(<span class="code-keyword">if</span>-let [smap (:source-map-asset-path opts)]
(emits <span class="code-quote">"\n<span class="code-comment">//# sourceMappingURL="</span> smap
</span> (string/replace (util/path sm-file)
(str (util/path (io/file (:output-dir opts))))
"")
(<span class="code-keyword">if</span> (and (<span class="code-keyword">true</span>? (:source-map-timestamp opts))
(not= (:target opts) :nodejs))
(str
(<span class="code-keyword">if</span>-not (string/index-of smap <span class="code-quote">"?"</span>) <span class="code-quote">"?"</span> <span class="code-quote">"&amp;"</span>)
<span class="code-quote">"rel="</span> timestamp)
""))
(emits <span class="code-quote">"\n<span class="code-comment">//# sourceMappingURL="</span>
</span> (or (:source-map-url opts) (.getName sm-file))
(<span class="code-keyword">if</span> (and (<span class="code-keyword">true</span>? (:source-map-timestamp opts))
(not= (:target opts) :nodejs))
(str <span class="code-quote">"?rel="</span> timestamp)
"")))
(spit sm-file
(sm/encode {(url-path src) (:source-map sm-data)}
{:lines (+ (:gen-line sm-data) 2)
:file (url-path dest)
:source-map-path (:source-map-path opts)
:source-map-timestamp (:source-map-timestamp opts)
:source-map-pretty-print (:source-map-pretty-print opts)
:relpaths {(util/path src)
(util/ns-&gt;relpath (first (:provides opts)) (:ext opts))}}))))</pre>
</div></div>CLJS-1864timestamped source maps broken with NodeDefectMinorOpenUnresolvedUnassignedDmitr SotnikovTue, 29 Nov 2016 17:42:10 -0600Wed, 30 Nov 2016 19:28:46 -06001.9.29311<p>Does Node.js have source map caching issues? The timestamp feature was created for caching issues present in web browsers.</p><p>I tried it with <tt>:source-map-timestamp</tt> set to false, and source maps got out of sync when Cljs sources were reloaded.</p><p>Okay. This issue will require more investigation into Node.js source mapping support before pursuing anything. As the behavior is understood, information should be added here.</p><p>Sounds like a plan.</p><p>OK I took a look at the implementation of source-map-support, it does indeed cache the source map. However the proposed idea here isn't comprehensive enough. We need to change all the places where :source-map-timestamp is used in the source code. Patch is welcome.</p><p>Yeah, I noticed the key is used in a few places. I can definitely take a look at making a patch in the near future if the approach looks good to you.</p>Global Rank[CLJS-1866] RangedIterator performance tweakshttp://dev.clojure.org/jira/browse/CLJS-1866
ClojureScript<p>The attached patch simplifies and speeds up the RangedIterator.</p>
<p>The benchmarks were run using the following function to test vector iteration:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(defn consume-iterator
[v]
(let [iter (-iterator v)]
(loop []
(when (.hasNext iter)
(.next iter)
(recur)))))
</pre>
</div></div>
<p>A series of "simple-benchmarks" were setup as follows: </p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(simple-benchmark [v (into [] (range N))] (consume-iterator v) I)
</pre>
</div></div>
<p>Where 'N' and 'I' were values from the 'Vector Size' and 'Iterations' columns of the table below .</p>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Vector Size</th>
<th class='confluenceTh'>Iterations</th>
<th class='confluenceTh'>V8 Speed <span class="error">&#91;msec&#93;</span> (master)</th>
<th class='confluenceTh'>V8 Speed <span class="error">&#91;msec&#93;</span> (patch)</th>
<th class='confluenceTh'>JSC Speed <span class="error">&#91;msec&#93;</span> (master)</th>
<th class='confluenceTh'> JSC Speed <span class="error">&#91;msec&#93;</span> (patch)</th>
</tr>
<tr>
<td class='confluenceTd'>1</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>15</td>
<td class='confluenceTd'>11</td>
<td class='confluenceTd'>13</td>
<td class='confluenceTd'>7</td>
</tr>
<tr>
<td class='confluenceTd'>2</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>14</td>
<td class='confluenceTd'>10</td>
<td class='confluenceTd'>7</td>
<td class='confluenceTd'>4</td>
</tr>
<tr>
<td class='confluenceTd'>4</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>18</td>
<td class='confluenceTd'>10</td>
<td class='confluenceTd'>9</td>
<td class='confluenceTd'>5</td>
</tr>
<tr>
<td class='confluenceTd'>8</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>27</td>
<td class='confluenceTd'>12</td>
<td class='confluenceTd'>14</td>
<td class='confluenceTd'>6</td>
</tr>
<tr>
<td class='confluenceTd'>16</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>43</td>
<td class='confluenceTd'>17</td>
<td class='confluenceTd'>19</td>
<td class='confluenceTd'>9</td>
</tr>
<tr>
<td class='confluenceTd'>32</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>74</td>
<td class='confluenceTd'>24</td>
<td class='confluenceTd'>37</td>
<td class='confluenceTd'>15</td>
</tr>
<tr>
<td class='confluenceTd'>100</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>217</td>
<td class='confluenceTd'>59</td>
<td class='confluenceTd'>105</td>
<td class='confluenceTd'>45</td>
</tr>
<tr>
<td class='confluenceTd'>1000</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>2008</td>
<td class='confluenceTd'>524</td>
<td class='confluenceTd'>1032</td>
<td class='confluenceTd'>392</td>
</tr>
<tr>
<td class='confluenceTd'>10,000</td>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>20390</td>
<td class='confluenceTd'>5856</td>
<td class='confluenceTd'>10249</td>
<td class='confluenceTd'>4178</td>
</tr>
<tr>
<td class='confluenceTd'>100,000</td>
<td class='confluenceTd'>10,000</td>
<td class='confluenceTd'>20334</td>
<td class='confluenceTd'>5324</td>
<td class='confluenceTd'>10324</td>
<td class='confluenceTd'>4387</td>
</tr>
</tbody></table>
<p>Javascript engine versions used:</p>
<ul>
<li>V8 version 5.1.281.47</li>
<li>JSC version Unknown</li>
</ul>
<p>The RangedIterator constructor function `ranged-iterator` was also made private.</p>CLJS-1866RangedIterator performance tweaksEnhancementMinorOpenUnresolvedUnassignedThomas MulvaneyperformanceThu, 8 Dec 2016 15:31:49 -0600Thu, 8 Dec 2016 15:31:49 -060000Global RankPatchCode[CLJS-633] Missing Java type hints in closure.cljhttp://dev.clojure.org/jira/browse/CLJS-633
ClojureScript<p>A number of reflection warnings are generated from closure.clj. Fixing those probably would not improved performance but it would be cleaner anyway.</p>CLJS-633Missing Java type hints in closure.cljEnhancementTrivialOpenUnresolvedUnassignedJulien EluardTue, 22 Oct 2013 08:00:08 -0500Tue, 22 Oct 2013 08:03:17 -050000<p>Attached patch.</p>
<p>There are a couple warnings left, similar to:<br/>
<em>Reflection warning, cljs/closure.clj:232:1 - reference to field url can't be resolved.</em><br/>
They appear to be due to some unexpected protocol method name? It looks harmless.</p>Global Rank[CLJS-872] Ordered collections printed as if they were unordered at the REPLhttp://dev.clojure.org/jira/browse/CLJS-872
ClojureScript<p>This is due to <tt>cljs.repl</tt>'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:</p>
<p><a href="https://github.com/clojure/clojurescript/blob/r2371/src/clj/cljs/repl.clj#L156">https://github.com/clojure/clojurescript/blob/r2371/src/clj/cljs/repl.clj#L156</a></p>
<p>A larger snippet to demonstrate this:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>ClojureScript:cljs.user&gt; (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&gt; (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&gt; (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&gt; (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}
</pre>
</div></div>
<p>This issue seems to be the most likely cause of the problem described in <a href="http://stackoverflow.com/questions/26349324/clojurescript-array-map-order">this StackOverflow question</a>. It would be nice to print ordered collections in the "expected" way to prevent user confusion.</p>CLJS-872Ordered collections printed as if they were unordered at the REPLDefectTrivialOpenUnresolvedUnassignedMichał MarczykMon, 13 Oct 2014 19:33:09 -0500Tue, 14 Oct 2014 08:07:12 -050001<p>How is this handled in Clojure?</p><p>The built-in REPL simply prints string representations of values to <tt>&#42;out*</tt> without attempting to read them back in first.</p><p>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 <tt>array-map</tt> promises anything about order anyway.</p><p>It does – see <a href="http://clojure.org/data_structures">http://clojure.org/data_structures</a>, where it says</p>
<blockquote>
<p>ArrayMaps<br/>
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.</p></blockquote>
<p>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 <tt>array-map</tt> (the core function) are unambiguous in their promise to construct array maps in both Clojure and ClojureScript.</p>
<p>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 <tt>pr-str</tt> on the same value. In fact, one way to fix this would be to use <tt>pr-str</tt> representations computed on the CLJS side. (There may be some complications here, though, which we'd have to work out.)</p><p>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 <img class="emoticon" src="http://dev.clojure.org/jira/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/></p>Global Rank[CLJS-507] Persistent Data Structure Benchmarkhttp://dev.clojure.org/jira/browse/CLJS-507
ClojureScript<p>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 <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=874174">http://bugzilla.mozilla.org/show_bug.cgi?id=874174</a></p>CLJS-507Persistent Data Structure BenchmarkTaskTrivialOpenUnresolvedUnassignedDavid NolenMon, 20 May 2013 14:35:42 -0500Tue, 2 Dec 2014 06:15:23 -060000Global Rank[CLJS-450] (ns) within (do) inconsistent with Clojure behaviourhttp://dev.clojure.org/jira/browse/CLJS-450
ClojureScript<p>An <tt>(ns)</tt> within a <tt>(do)</tt> doesn't quite work as expected at the REPL:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">ClojureScript:cljs.user&gt; (<span class="code-keyword">do</span> (ns foo) (def x 42))
nil
ClojureScript:foo&gt; x
nil
ClojureScript:cljs.user&gt; cljs.user/x
42</pre>
</div></div>
<p>The Clojure equivalent:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">user=&gt; (<span class="code-keyword">do</span> (ns foo) (def x 42))
#'foo/x
foo=&gt; x
42</pre>
</div></div>CLJS-450(ns) within (do) inconsistent with Clojure behaviourDefectTrivialOpenUnresolvedUnassignedStuart CampbellThu, 27 Dec 2012 19:15:34 -0600Sat, 21 Feb 2015 07:25:15 -060002<p>Looks like we need to do something similar to what is done in Clojure with top level do - <a href="http://github.com/frenchy64/typed-clojure/pull/4">http://github.com/frenchy64/typed-clojure/pull/4</a></p>Global Rank[CLJS-1009] Allow deps.cljs to declare a foreign lib as remotehttp://dev.clojure.org/jira/browse/CLJS-1009
ClojureScript<p>When using things like the Google Maps JS API <span class="error">&#91;1&#93;</span> the Javascript that is required can't be bundled inside a jar as it depends on the used API key.</p>
<p>To be able to provide externs for those kind of libraries there should be a way to declare them as "remote" in <tt>deps.cljs</tt>.</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://developers.google.com/maps/documentation/javascript/tutorial">https://developers.google.com/maps/documentation/javascript/tutorial</a></p>CLJS-1009Allow deps.cljs to declare a foreign lib as remoteEnhancementTrivialOpenUnresolvedUnassignedMartin KlepschThu, 5 Feb 2015 13:54:42 -0600Sat, 21 Feb 2015 07:53:18 -060010Global Rank[CLJS-555] CLONE - Implement ratioshttp://dev.clojure.org/jira/browse/CLJS-555
ClojureScript<p>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:</p>
<ul class="alternate" type="square">
<li>`ratio?`</li>
<li>`numerator`</li>
<li>`denominator`</li>
<li>`rationalize`</li>
</ul>
<p>Plus the ratio type would need to be rolled into the existing mathematical frameworkings.</p>
<p>Imported from github issue #66</p>CLJS-555CLONE - Implement ratiosEnhancementTrivialOpenUnresolvedUnassignedStuart HallowaySat, 27 Jul 2013 12:56:07 -0500Tue, 2 Dec 2014 06:14:58 -060021<p>Lower priority, unsolvable without numerics overhaul.</p>Global Rank[CLJS-1185] Support preambles when our target is node.js and we are compiler a main filehttp://dev.clojure.org/jira/browse/CLJS-1185
ClojureScriptCLJS-1185Support preambles when our target is node.js and we are compiler a main fileEnhancementTrivialOpenUnresolvedUnassignedIvan WilligThu, 2 Apr 2015 14:47:50 -0500Thu, 2 Apr 2015 16:07:56 -050000Global Rank[CLJS-1251] Missing semicolons when emitting deftype and defrecordhttp://dev.clojure.org/jira/browse/CLJS-1251
ClojureScript<p>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).</p>
<p>The bad case: <br/>
If body has the first statement wrapped in (...), javascript will treat it as a function call on the constructor definition.</p>CLJS-1251Missing semicolons when emitting deftype and defrecordDefectTrivialOpenUnresolvedUnassignedAntonin HildebrandThu, 7 May 2015 01:09:37 -0500Thu, 7 May 2015 01:12:53 -050000Global Rank[CLJS-1295] Improve doc for instancehttp://dev.clojure.org/jira/browse/CLJS-1295
ClojureScript<p>Doc for instance? does not reflect argument names.</p>CLJS-1295Improve doc for instanceEnhancementTrivialOpenUnresolvedUnassignedJulien EluardMon, 1 Jun 2015 14:23:07 -0500Mon, 1 Jun 2015 14:23:20 -050000Global Rank[CLJS-1378] JARs that end in .exe are problematichttp://dev.clojure.org/jira/browse/CLJS-1378
ClojureScript<p>compile-from-jar cannot handle the later form</p>
<p>{{jar:<a href="file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.jar!/cljs/com/walmart/test/app.cljs">file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.jar!/cljs/com/walmart/test/app.cljs</a>}}<br/>
{{jar:<a href="file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.exe!/cljs/com/walmart/test/app.cljs">file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.exe!/cljs/com/walmart/test/app.cljs</a>}}</p>CLJS-1378JARs that end in .exe are problematicDefectTrivialOpenUnresolvedUnassignedDavid NolenWed, 29 Jul 2015 16:06:38 -0500Thu, 30 Jul 2015 15:26:14 -05000.0-330800Global Rank[CLJS-324] cljs.core/formathttp://dev.clojure.org/jira/browse/CLJS-324
ClojureScript<p>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?</p>CLJS-324cljs.core/formatEnhancementTrivialReopenedUnresolvedUnassignedGary FredericksSun, 24 Jun 2012 18:50:21 -0500Wed, 11 Mar 2015 14:26:12 -050014<p>GClosure does actually include a string formatter &#8211; 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 &#8211; not tested, but should work).</p>
<p>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 <a href="http://dev.clojure.org/jira/browse/CLJS-328" title="Bugfix for :require spec handling in ns"><del>CLJS-328</del></a>.</p>
<p>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).</p><p>The tests fail for me with this patch applied.</p><p>fixed, <a href="http://github.com/clojure/clojurescript/commit/8f518760a3df8b351208e97bb70270856623bb0a">http://github.com/clojure/clojurescript/commit/8f518760a3df8b351208e97bb70270856623bb0a</a></p><p>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.</p><p>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 <a href="http://localhost:3000/">http://localhost:3000/</a></p>
<p>The code in hello.cljs shows that goog.string.toTitleCase works, but not goog.string.format.</p><p>It looks like you are not requiring correctly format. See a working example <a href="https://github.com/noprompt/garden/blob/master/src/cljx/garden/util.cljx#L7">here</a>.</p><p>Julent, thanks! It needs another <span class="error">&#91;goog.string.format&#93;</span> after <span class="error">&#91;goog.string :as gstring&#93;</span> before you can use gstring/format. hello.cljs now looks like this, and throws no exceptions: <a href="https://www.refheap.com/19693">https://www.refheap.com/19693</a></p>
Global Rank[CLJS-1549] Printing #object tags should be consistenthttp://dev.clojure.org/jira/browse/CLJS-1549
ClojureScript<p>[<a href="http://dev.clojure.org/jira/browse/CLJS-1376" title="Printing in a tagged literal data form"><del>CLJS-1376</del></a>|http://dev.clojure.org/jira/browse/CLJS-1376) wanted to bring printing parity with Clojure 1.7.0.</p>
<p>There are two problems:<br/>
1) Atom and Volatile contain extra space between #object and "[" (that differs from Clojure 1.7.0)<br/>
2) Atom and Volatile printing was inconsistent with #object printing in pr-writer-impl (in goog/isFunction and :else branches) - there we have no space</p>
<p>I have introduced a function which handles printing object tags consistently without space. Also I have broken writing content into writer into logical tokens for easier cljs-devtools implementation.</p>
<p>Background info:<br/>
Exact printing behaviour is quite important for me when implementing alternative pr-writer-impl for cljs-devtools. For most cases I call original pr-writer-impl and then post-process its output to enhance its presentation in DevTools console:<br/>
<a href="https://github.com/binaryage/cljs-devtools/blob/2f1c0f4095a364bb11a833e73e5753a4e48add8f/src/devtools/format.cljs#L200-L226">https://github.com/binaryage/cljs-devtools/blob/2f1c0f4095a364bb11a833e73e5753a4e48add8f/src/devtools/format.cljs#L200-L226</a></p>
<p>In case of constructors or functions (goog/isFunction and :else branches of pr-writer-impl), I don't want to emit stringified content, but I want to provide real js-object reference and delegate further printing/expansion to native javascript formatter in DevTools.<br/>
In other cases like Atom or Volatile, I would like to easily detect "#object" as first token written into writer and provide better visual clues. I find printing "#object <span class="error">&#91;...&#93;</span>" confusing for more complex data situations. Square brackets resemble vectors and may confuse clarity. Instead I will use color-coding or another form of visual styling to mark object instances and their boundaries. But for this I want to have nice token stream "#object" "<span class="error">&#91;&quot; ... &quot;&#93;</span>" without having to use regexps.</p>CLJS-1549Printing #object tags should be consistentEnhancementTrivialOpenUnresolvedUnassignedAntonin HildebrandFri, 22 Jan 2016 11:35:48 -0600Fri, 29 Jan 2016 20:01:59 -060000Global RankPatchCode[CLJS-924] Better error message for mistaken use of 'def'http://dev.clojure.org/jira/browse/CLJS-924
ClojureScript<p>ClojureScript shares what is IMHO one of the biggest weaknesses of the current JVM Clojure implementation: those (in)famous stack traces going down into the innards of the compiler if you get your syntax wrong. An easy mistake for noobs is to use 'def' in place of 'defn'; this patch makes that mistake a lot less painful to debug.</p>
<p>Feedback please!</p>CLJS-924Better error message for mistaken use of 'def'EnhancementTrivialOpenUnresolvedUnassignedAlex DowadWed, 24 Dec 2014 10:32:28 -0600Sat, 20 Feb 2016 21:49:58 -060001<p>Patch no longer applies.</p><p>Revised patch <a href="http://dev.clojure.org/jira/browse/CLJS-924" title="Better error message for mistaken use of &#39;def&#39;">CLJS-924</a>.patch applies to master. </p>
<p>(Based on Alex Dowad's original patch. Both Alex and I have signed the CA.)</p>Global RankPatchCode[CLJS-1450] Arithmetic warning thrown for impossible conditionhttp://dev.clojure.org/jira/browse/CLJS-1450
ClojureScript<p>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.)</p>
<p>The exact warning triggered is below, followed by the code.</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>WARNING: cljs.core/+, all arguments must be numbers, got [number clj-nil] instead. at line 22 src\spurious_arithmetic\core.cljs
</pre>
</div></div>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>(def x [0 1 2 3 4 nil])
(def index (atom -1))
(defn take-value []
(-&gt;&gt; (swap! index inc)
(nth x)))
(-&gt; (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
</pre>
</div></div>CLJS-1450Arithmetic warning thrown for impossible conditionDefectTrivialOpenUnresolvedUnassignedQuest YarbroughbugcompilerTue, 15 Sep 2015 20:17:30 -0500Wed, 30 Mar 2016 23:33:22 -05001.7.4801<p>The type inference logic in the compiler expects that the type of a loop local is static. In fact, somewhat the opposite of this ticket is being done in <a href="http://dev.clojure.org/jira/browse/CLJS-1561" title="WARN if recur passes non-inferred type">CLJS-1561</a>.</p>Global Rank[CLJS-1676] Unused local in ObjMap / IKVReducehttp://dev.clojure.org/jira/browse/CLJS-1676
ClojureScript<p>Local len isn't used in ObjMap / IKVReduce</p>
<p><a href="https://github.com/clojure/clojurescript/blob/463de005b81d4a00951188e8b8d38a61d684c18e/src/main/cljs/cljs/core.cljs#L5792">https://github.com/clojure/clojurescript/blob/463de005b81d4a00951188e8b8d38a61d684c18e/src/main/cljs/cljs/core.cljs#L5792</a></p>CLJS-1676Unused local in ObjMap / IKVReduceDefectTrivialOpenUnresolvedUnassignedStuart HinsonThu, 9 Jun 2016 14:13:49 -0500Thu, 9 Jun 2016 14:20:04 -05001.9.3600Global Rank[CLJS-1714] Clojurescript github README.md should identify source Clojure versionhttp://dev.clojure.org/jira/browse/CLJS-1714
ClojureScript<p>It would be helpful if the Clojurescript README at <a href="https://github.com/clojure/clojurescript/blob/master/README.md">https://github.com/clojure/clojurescript/blob/master/README.md</a> explicitly identified the Clojure version on which the current stable release of Clojurescript is based, or the Clojure version(s) which the Clojurescript release most closely tracks. This is especially helpful during periods when the Clojurescript release recommended in README.md is based on a Clojure alpha or even beta version, since there may be significant changes between Clojure versions in this case, so users might expect more similarity between the latest public releases of the two dialects than is warranted. Of course one can also go through changes.md to figure out what Clojure version is the basis of each Clojurescript release, but I think it's worth making it easier for users to notice.</p>CLJS-1714Clojurescript github README.md should identify source Clojure versionEnhancementTrivialOpenUnresolvedUnassignedMarshall AbramsSun, 24 Jul 2016 12:09:11 -0500Tue, 26 Jul 2016 00:39:10 -050000<p>ClojureScript depends only on final releases of Clojure. This dependency is expressed in the pom.xml file which Maven based tooling and its users already understand. I don't see a compelling reason to include yet another thing we have to remember to update in the README.</p><p>First, I'm not sure if what I wrote was clear. I'm not talking about a dependency on the Clojure version used to compile to Javascript. I'm talking about the relationship between a Clojurescript version and the Clojure version that was ... ported to the Clojurescript release.</p>
<p>I agree it would a pain to try to remember to update this each time the Clojurescript version changed. That was one of my reservations, but I thought the point was important enough-especially for new users-that it seemed worth suggesting. I suppose that if there was already a line in the README about it, that will help, but I know that it's still easy to forget to update that kind of thing. Can't be helped.</p>
<p>Here are some reasons to consider updating the README with the Clojure version(s) that are the "source" of a Clojurescript version:</p>
<p>It's very useful information what version of Clojure the current Clojurescript release is most similar to. That way, information about the Clojure version is useful for Clojurescript.</p>
<p>At present, the official releases of Clojurescript listed in the README is based on what are currently alpha Clojure releases. Since the Clojure releases are alpha releases, they're changing quickly, so whatever's documented on the Clojure website may be out of sync with the Clojurescript release. One needs to know if that's so. (If all I want from the current Clojurescript release is what's in the previous non-alpha/beta Clojure release, knowing the Clojure version that was the source probably doesn't matter if there have been no breaking changes in the alpha releases on which the current Clojurescript version is based, but if I want to experiment in Clojurescript with new Clojure features-spec in this case-I need to know if it might differ from the latest Clojure version. (<tt>explain-data</tt> changed from Clojure 1.9.0-alpha7 to alpha10, at least.)</p>
<p>(I think that the comment about Maven and pom.xml was based on assuming that I was talking about the Clojure version used to compile Clojurescript code. <b>If so, you can stop reading this paragraph.</b> If not, then I would say that though Maven may be routinely used by Clojurescript developers-I don't know-but Clojurescript has grown beyond a core community of hardcore users and developers. It's used for a lot of real work, and it's a good language for new users coming from Clojure or Javascript. There are books for sale, and good online tutorials. The wiki is quite good for new users now. All of the templates on the wiki use Leiningen or Boot. There's no mention of Maven. There is no need for most users to use Maven with Clojurescript, or to even know what a pom file is. In my case, I do know what a pom file is, and have read quite a few, but wouldn't have thought to look there. I've never used Maven, however. Leiningen has been enough.)</p>
<p>Those are my thoughts on the matter. Thanks much for considering it.</p>Global Rank[CLJS-1724] Include IIterable in fast-path-protocolshttp://dev.clojure.org/jira/browse/CLJS-1724
ClojureScript<p>While exploring CLJS record instances printed via cljs-devtools v0.8.0, I spotted that IIterable is not a fast-path protocol:</p>
<p><a href="https://dl.dropboxusercontent.com/u/559047/iiterable-slow-path.png">https://dl.dropboxusercontent.com/u/559047/iiterable-slow-path.png</a></p>
<p>Please notice that IIterable is the only white label in the protocol list there.</p>CLJS-1724Include IIterable in fast-path-protocolsEnhancementTrivialOpenUnresolvedUnassignedAntonin HildebrandThu, 4 Aug 2016 13:40:18 -0500Thu, 4 Aug 2016 13:42:41 -050000Global Rank[CLJS-1725] defrecord does not set cljs$lang$ctorStrhttp://dev.clojure.org/jira/browse/CLJS-1725
ClojureScript<p>While implementing some demunging code<span class="error">&#91;1&#93;</span> for cljs-devtools, I stumbled upon inconsistency in type-&gt;str. It works for deftypes but not for defrecords.</p>
<p>The problem is that defrecord does not set! cljs$lang$ctorStr field for some reason. This has been likely overlooked, because type-&gt;str is not used often, just for some rare error exceptions as far I can see.</p>
<p>Anyways, this patch fixes it by copy&amp;pasting it from deftype. A better solution to avoid future problems like this would be to extract shared code between deftypes and defrecords, but that seems to be a lot of work.</p>
<p>The patch also adds some tests. I had to add some utility macros to run those tests only in simple mode, because type-&gt;str is not supposed to work under advanced builds.<br/>
Also test for <a href="http://dev.clojure.org/jira/browse/CLJS-1722" title="Upgrade ExceptionInfo to proper deftype">CLJS-1722</a> was added to be uncommented after potentially merging it.</p>
<p><span class="error">&#91;1&#93;</span> <a href="https://github.com/binaryage/cljs-devtools/blob/52899e61e33373df36be8dcb23c69377936821b2/src/lib/devtools/munging.cljs#L56-L60">https://github.com/binaryage/cljs-devtools/blob/52899e61e33373df36be8dcb23c69377936821b2/src/lib/devtools/munging.cljs#L56-L60</a></p>CLJS-1725defrecord does not set cljs$lang$ctorStrDefectTrivialOpenUnresolvedUnassignedAntonin HildebrandThu, 4 Aug 2016 13:54:28 -0500Thu, 4 Aug 2016 15:30:09 -050000Global RankPatchCode and Test[CLJS-1723] pr-writer-ex-info does not print false values and tries to reimplement map printerhttp://dev.clojure.org/jira/browse/CLJS-1723
ClojureScript<p>While working on <a href="http://dev.clojure.org/jira/browse/CLJS-1722" title="Upgrade ExceptionInfo to proper deftype">CLJS-1722</a> I spotted two issues with pr-writer-ex-info:</p>
<p>1) if data or cause happen to be "false", they are skipped in printing<br/>
2) the code tries to mimic map printer</p>
<p>This patch fixes both issues. It turns out printing real info map yields exactly same string output and plays better with cljs-devtools printer (which newly sees real map instead of soup of strings and values).</p>
<p>For reference: pr-writer-ex-info was implemented in <a href="http://dev.clojure.org/jira/browse/CLJS-983" title="Make ExceptionInfo printable"><del>CLJS-983</del></a></p>CLJS-1723pr-writer-ex-info does not print false values and tries to reimplement map printerDefectTrivialOpenUnresolvedUnassignedAntonin HildebrandThu, 4 Aug 2016 13:24:50 -0500Mon, 8 Aug 2016 14:32:28 -050000<p>Can you explain why you think 1 is a problem? data should be a map. cause should be an error but I suppose that could be a problem if you have a rethrow which wraps some throwable value (which of course could be anything).</p><p>Disclaimer: I don't have much experience with Clojure and almost none with Java.</p>
<p>Just by reading the code I didn't see any checks in ex-info (or in ExceptionInfo ctor) to restrict data or cause. So I assumed anything can be passed in and printer should print it as-is without additional logic. I assumed that checking for nil values was intentional abbreviation when <a href="http://dev.clojure.org/jira/browse/CLJS-983" title="Make ExceptionInfo printable"><del>CLJS-983</del></a> was implemented. And I assumed that false value was supposed to be printed. At least I personally would want it to be distinguished from nil. Or there should be no abbreviation at all.</p>Global RankPatchCode[CLJS-1743] Transient{Hash,Array}Map should support IFn like in Clojurehttp://dev.clojure.org/jira/browse/CLJS-1743
ClojureScript<p>Users should be able to invoke transient maps like in Clojure.</p>CLJS-1743Transient{Hash,Array}Map should support IFn like in ClojureEnhancementTrivialOpenUnresolvedUnassignedThomas MulvaneySat, 13 Aug 2016 16:47:52 -0500Sat, 13 Aug 2016 16:54:56 -050000Global RankPatchCode and Test[CLJS-884] with-redefs don't restores previous values when used inside go blockhttp://dev.clojure.org/jira/browse/CLJS-884
ClojureScript<p>For example I have code and test:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn test-fn [] :original)
(deftest ^:async test-with-redefs-async
(go (is (= (test-fn) :original))
(with-redefs [test-fn (fn [] :mocked)]
(is (= (test-fn) :mocked)))
(is (= (test-fn) :original))
(done)))</pre>
</div></div>
<p>And test failed in last `is`:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">FAIL in (test-with-redefs-async) (:)
expected: (= (test-fn) :original)
actual: (not (= :mocked :original))</pre>
</div></div>clojure 1.6, clojurescript 0.0-2371, core.async 0.1.346.0-17112a-alphaCLJS-884with-redefs don't restores previous values when used inside go blockDefectTrivialOpenUnresolvedUnassignedVladimir IakovlevSun, 9 Nov 2014 13:16:31 -0600Sun, 7 Aug 2016 23:26:56 -050043<p>I attached little patch with fix. With it `with-redefs` forced to use previous value for restoring bindings.</p>
<p>But I don't know how to add test for this issue, because it requires core.async. So I tested with:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(defn test-fn [] :original)
(deftest test-with-redefs-sync
(is (= (test-fn) :original))
(with-redefs [test-fn (fn [] :mocked)]
(is (= (test-fn) :mocked)))
(is (= (test-fn) :original)))
(deftest ^:async test-with-redefs-async
(go (is (= (test-fn) :original))
(with-redefs [test-fn (fn [] :mocked)]
(is (= (test-fn) :mocked)))
(is (= (test-fn) :original))
(done)))</pre>
</div></div><p>Why this bug is not adressed?</p><p>It might be related to <a href="http://dev.clojure.org/jira/browse/CLJS-1634" title="Track bound dynamic variables to support binding in async mechanisms.">CLJS-1634</a>. The likely reason: it is technically very hard to solve without paying non-negligible runtime price for it.</p><p>The problem mentioned in <a href="http://dev.clojure.org/jira/browse/CLJS-1634">http://dev.clojure.org/jira/browse/CLJS-1634</a> is much wider.</p>
<p>The current issue only deals with the fact that `with-redefs` doen't restore previous values when used inside go block.</p>
<p>There is a very simple solution to this specific issue here: <a href="https://nvbn.github.io/2014/11/05/protocols-for-testing/">https://nvbn.github.io/2014/11/05/protocols-for-testing/</a> (also written by Vladimir).</p>Global Rank[CLJS-1769] Use reduce pathway for arrays in js->cljhttp://dev.clojure.org/jira/browse/CLJS-1769
ClojureScript<p>Currently js-&gt;cljs uses `(vec (map some-fn some-js-array))` on arrays. By using `(mapv some-fn some-js-array)` we take advantage of array-reduce and avoid a lazy-sequence.</p>CLJS-1769Use reduce pathway for arrays in js->cljEnhancementTrivialOpenUnresolvedUnassignedThomas MulvaneyThu, 1 Sep 2016 11:52:48 -0500Thu, 1 Sep 2016 12:00:58 -050000Global RankPatchCode[CLJS-1793] Few misplaced docstringshttp://dev.clojure.org/jira/browse/CLJS-1793
ClojureScript<p>A few docsctrings were placed after the binding form in the src/main/clojure/cljs/closure.clj namespace.</p>CLJS-1793Few misplaced docstringsDefectTrivialOpenUnresolvedUnassignedThomas MulvaneySat, 24 Sep 2016 00:10:08 -0500Sat, 24 Sep 2016 03:23:17 -050000Global Rank[CLJS-1696] Alias clojure.spec.gen => cljs.spec.impl.genhttp://dev.clojure.org/jira/browse/CLJS-1696
ClojureScript<p>A special case for <a href="http://dev.clojure.org/jira/browse/CLJS-1692">http://dev.clojure.org/jira/browse/CLJS-1692</a> to correctly alias clojure.spec.gen.</p>
CLJS-1696Alias clojure.spec.gen => cljs.spec.impl.genDefectTrivialOpenUnresolvedUnassignedShaun LeBronWed, 29 Jun 2016 11:59:57 -0500Fri, 16 Sep 2016 14:20:59 -050011<p>code and test</p><p>I'm not excited about special casing this one. I'd rather wait to see if people actually use this namespace frequently enough for this to be desirable.</p><p>yeah, i guess the question is who should be responsible for handling this special case-- the user with reader conditionals or the compiler with this patch.</p>
<p>for extra context, I asked about this last week in slack: <a href="https://clojurians.slack.com/archives/clojurescript/p1466866626001218">https://clojurians.slack.com/archives/clojurescript/p1466866626001218</a></p>
<p>Just to bump this, I see references to requiring clojure.spec.gen in a few places now. The Clojure spec guide mentions it in project setup for generators, and the Clojure spec screencast on customizing generators.</p>
<p>One possibly related point. It seems necessary to require `clojure.test.check` in order for requiring `cljs.spec.impl.gen` to work.</p>Global Rank[CLJS-1771] Add helper for converting ex-info to js/Errorhttp://dev.clojure.org/jira/browse/CLJS-1771
ClojureScript<p>ex-info/ex-data/ex-message didn't get a lot of attention in CLJS community, still I find quiet often (js/Error. "Err"). I guess the main reason is that we cannot pass ex-info object back to JS world, clj-&gt;js doesn't work in this case. We can solve it by adding helper like ex-&gt;js which will convert ex-info backward to js/Error.</p>
<p>What do you think about such enhancement? I can add patch later if you would find it useful</p>CLJS-1771Add helper for converting ex-info to js/ErrorEnhancementTrivialOpenUnresolvedUnassignedArtem Yarulinex-infoFri, 2 Sep 2016 02:37:01 -0500Fri, 2 Sep 2016 02:37:01 -05001.9.7601Global Rank[CLJS-1593] Self-host: Munged minus macrohttp://dev.clojure.org/jira/browse/CLJS-1593
ClojureScript<p>In bootstrap, the macro form of <tt>cljs.core/-</tt> is evidently available as <tt>_</tt> so, for example <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">(_ 7 3)</pre>
</div></div> works.</p>
<p>Repro:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">cljs.user=&gt; (require 'cljs.js)
nil
cljs.user=&gt; (cljs.js/eval-str (cljs.js/empty-state)
<span class="code-quote">"(_ 7 3)"</span> nil {:eval cljs.js/js-eval :context :expr} identity)
{:ns cljs.user, :value 4}</pre>
</div></div>CLJS-1593Self-host: Munged minus macroDefectTrivialOpenUnresolvedUnassignedMike FikesbootstrapThu, 25 Feb 2016 14:32:19 -0600Sat, 28 May 2016 13:55:50 -050012Global Rank[CLJS-1533] Null pointer error on non-existent file in advanced modehttp://dev.clojure.org/jira/browse/CLJS-1533
ClojureScript<p>When building without optimisations, having a foreign-lib point to a non-existent file gives a fairly clear <tt>FileNotFoundException</tt></p>
<p>When doing the same build but with advanted optimisations, the much more cryptic error <tt>java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil</tt> is given</p>
<p>Repo with code that reproduces and full bash output is here: <a href="https://gist.github.com/glenjamin/2614f71a50dbbccf9040">https://gist.github.com/glenjamin/2614f71a50dbbccf9040</a></p>CLJS-1533Null pointer error on non-existent file in advanced modeDefectTrivialOpenUnresolvedUnassignedGlen Mailererror-reportingFri, 1 Jan 2016 18:12:20 -0600Mon, 7 Nov 2016 10:09:23 -060001<p>Can't repro in 1.9.293. I get the expected FileNotFoundException.</p>Global Rank[CLJS-1865] Google Closure Compiler in JavaScripthttp://dev.clojure.org/jira/browse/CLJS-1865
ClojureScript<p>Google released its JavaScript version of the Closure Compiler &#8211; "this allows Closure Compiler to run entirely in JS. Java is not required": </p>
<ul>
<li><a href="https://github.com/google/closure-compiler-js">https://github.com/google/closure-compiler-js</a></li>
<li><a href="https://developers.googleblog.com/2016/08/closure-compiler-in-javascript.html">https://developers.googleblog.com/2016/08/closure-compiler-in-javascript.html</a></li>
</ul>
<p>Switching to the JS compiler means JS devs coming to ClojureScript will be able to use the tools they're familiar with a simplify the onboarding docs on the website. </p>
<p>NB: I discovered this while experimenting with using ClojureScript with Polymer:</p>
<ul>
<li><a href="https://medium.com/dev-channel/polymer-the-closure-compiler-e80dd249d9d7#.10xytauqf">https://medium.com/dev-channel/polymer-the-closure-compiler-e80dd249d9d7#.10xytauqf</a></li>
<li><a href="http://closuretools.blogspot.com/2016/06/using-polymer-with-closure-compiler-part-1.html">http://closuretools.blogspot.com/2016/06/using-polymer-with-closure-compiler-part-1.html</a></li>
</ul>
CLJS-1865Google Closure Compiler in JavaScriptEnhancementTrivialOpenUnresolvedUnassignedJames ThorntonTue, 6 Dec 2016 11:17:22 -0600Tue, 6 Dec 2016 11:26:18 -06001.9.3611Global Rank