<< Back to previous view

[CLJS-1891] UUID.toString can return non-string Created: 18/Jan/17  Updated: 18/Jan/17

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

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


 Description   

Summary

An incorrectly-constructed UUID can cause TypeError from str.

Detail

The cljs.core/uuid constructor stores its argument in the uuid field of the UUID deftype. See core.cljs line 10400.

It is assumed that this field is the string representation of the UUID, so it is also the return value of returned from UUID.toString. See core.cljs line 10377.

In correct code, the argument to cljs.core/uuid will never be anything but a string, so this is safe. But incorrect code can call cljs.core/uuid on any type, such as an Object. This leads to the following error when attempting to convert the UUID back into a string:

cljs.user=> (str (uuid #js{:foo "bar"}))
#object[TypeError TypeError: Cannot convert object to primitive value]
   Function.cljs.core.str.cljs$core$IFn$_invoke$arity$1 (jar:file:~/.m2/repository/org/clojure/clojurescript/1.9.225/clojurescript-1.9.225.jar!/cljs/core.cljs:2782:22)
   cljs$core$str (jar:file:~/.m2/repository/org/clojure/clojurescript/1.9.225/clojurescript-1.9.225.jar!/cljs/core.cljs:2775:1)
nil

The error is thrown from arity-1 of cljs.core/str, which coerces its argument to a string by wrapping it in a JavaScript array and calling Array.join; see core.cljs line 2819

Presumably the implementation of Array.join is calling toString on the object. toString returns something which is not a string and cannot be coerced into a string, leading to the TypeError. This can be demonstrated more directly with:

cljs.user=> (str #js{:toString (fn [] #js{})})
#object[TypeError TypeError: Cannot convert object to primitive value]
   Function.cljs.core.str.cljs$core$IFn$_invoke$arity$1 (jar:file:/Users/stuart/.m2/repository/org/clojure/clojurescript/1.9.225/clojurescript-1.9.225.jar!/cljs/core.cljs:2782:22)
   cljs$core$str (jar:file:/Users/stuart/.m2/repository/org/clojure/clojurescript/1.9.225/clojurescript-1.9.225.jar!/cljs/core.cljs:2775:1)
nil

Although the ECMAscript specifications are vague on the subject, it seems safe to say that it is incorrect for toString to return anything which is not a string.

Related

CLJS-1599, "UUIDs are not equal for upper/lower case strings," also relates to construction of UUIDs.






[CLJS-536] clj->js trims the namespace prefix from keywords while writing them to string Created: 12/Jul/13  Updated: 17/Jan/17  Resolved: 02/Dec/13

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

Type: Defect Priority: Major
Reporter: Vasile Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: clj->js

Attachments: Text File 0001-CLJS-536-Add-support-for-namespaced-keywords.patch     Text File 0001-CLJS-536-Add-support-for-namespaced-keywords.patch    

 Description   

The following behavior was observed and confirmed from the code:

(clj->js :ns/n) => "n"

I believe this is a limitation and the namespace of the keyword should be kept while writing it to string.
The code in core.js does this while handling keywords:

(keyword? x) (name x)

while it should do this (or something similar):

(keyword? x) (str (namespace x) "/" (name x))



 Comments   
Comment by Vasile [ 12/Jul/13 12:03 PM ]

a better (working) fix: (keyword? x) (str (if (namespace x) (str (namespace x) "/")) (name x))

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

I'd be willing to take a patch that allows this behavior to be configured.

Comment by Niklas Närhinen [ 01/Nov/13 7:33 AM ]

Proposed fix

Comment by Niklas Närhinen [ 01/Nov/13 7:37 AM ]

Fixed version of patch

Comment by David Nolen [ 01/Nov/13 9:23 AM ]

Excellent, Niklas I don't see you on the list of contributors, please send in your Contributor Agreement, http://clojure.org/contributing, so we can apply the patch.

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

I looked more closely at the clj->js source, the system is already customizable. We can't determine ahead of time how you might want to emit keywords and symbols - thus you can extend Keyword and Symbol to IEncodeJS yourself and get the desired behavior.

Comment by Andrea Richiardi [ 17/Jan/17 2:52 PM ]

I have just stumbled across this one, shall we at least say it in the docstring of clj->js that we are losing the namespace part?





[CLJS-1890] s/form for s/nilable in cljs.spec does not match clojure.spec Created: 17/Jan/17  Updated: 17/Jan/17

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

Type: Defect Priority: Major
Reporter: Miikka Koskinen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Clojure 1.9-alpha14



 Description   
Clojure
user=> (s/form (s/nilable int?))
(clojure.spec/nilable clojure.core/int?)
ClojureScript
cljs.user=> (s/form (s/nilable int?))
(cljs.spec/and (cljs.spec/or :cljs.spec/nil cljs.core/nil? :cljs.spec/pred cljs.core/int?) (cljs.spec/conformer cljs.core/second))

What I expected from ClojureScript was (cljs.spec/nilable cljs.core/int?).






[CLJS-1886] RangedIterator should only be created from cljs.core.PersistentVector instances Created: 10/Jan/17  Updated: 17/Jan/17

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

Type: Defect Priority: Minor
Reporter: ewen grosjean Assignee: ewen grosjean
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1886.patch    
Patch: Code

 Description   

RangedIterator uses cljs.core.PersistentVector internals and thus should not be created from other types of vectors. subvec does not follow this rule.



 Comments   
Comment by ewen grosjean [ 10/Jan/17 5:21 AM ]

This fixes a regression introduced by http://dev.clojure.org/jira/browse/CLJS-1855.

Comment by David Nolen [ 11/Jan/17 7:08 AM ]

Does this patch match the implementation approach in Clojure? Thanks.

Comment by ewen grosjean [ 11/Jan/17 11:08 AM ]

Yes, the Clojure approach is to check the type of the wrapped vector and to use a ranged iterator on instances of APersistentVector. It falls back to a more general iterator when the wrapped vector is not an instance of APersistentVector.
https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/jvm/clojure/lang/APersistentVector.java#L565

Comment by David Nolen [ 16/Jan/17 4:51 PM ]

Hrm that's not really the same since Clojure is checking for an interface. We probably want to replicate this behavior by using a marker protocol and testing for it with `implements?`.

Comment by ewen grosjean [ 17/Jan/17 5:39 AM ]

Clojurescript's ranged iterator goes quite deep into the persistent vector implementation details. Shouldn't marker protocol be used to mark abstract things ?

Comment by David Nolen [ 17/Jan/17 5:56 AM ]

That's not how we use marker protocols in ClojureScript so I'm not really concerned about that. This is something for expert implementers anyhow.





[CLJS-1887] add :watch-error-fn option Created: 12/Jan/17  Updated: 16/Jan/17  Resolved: 16/Jan/17

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

Type: Enhancement Priority: Minor
Reporter: Shaun LeBron Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1887.patch    

 Description   

Like `:watch-fn` notifies on a successful build, the proposed `:watch-error-fn` can notify on a failed one.

See: https://github.com/clojure/clojurescript/wiki/Compiler-Options#watch-fn



 Comments   
Comment by Shaun LeBron [ 12/Jan/17 11:11 PM ]

Had some fun verifying this with figwheel-sidecar's `print-exception` function:
https://github.com/cljs/tool/blob/watch-fig-errors/target/script/watch.clj

Comment by David Nolen [ 16/Jan/17 4:49 PM ]

fixed https://github.com/clojure/clojurescript/commit/5603b313de751f0d7344b7ae790ce0591fab5f77





[CLJS-1889] A lone ampersand `&` can be used to name a var, but throws when invoked. `(&)` Created: 15/Jan/17  Updated: 16/Jan/17

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

Type: Defect Priority: Trivial
Reporter: Aleksander Madland Stapnes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I can use the symbol & to name something, but if I try to invoke it, the following exception is thrown:

Exception in thread "main" clojure.lang.ExceptionInfo: failed compiling file:src/amp/core.cljs {:file #object[java.io.File 0x5e63cad "src/amp/core.cljs"]}, compiling/home/madstap/code/ampersand/build.clj:3:1)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$script_opt.invokeStatic(main.clj:335)
at clojure.main$script_opt.invoke(main.clj:330)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
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)
Caused by: clojure.lang.ExceptionInfo: failed compiling file:src/amp/core.cljs {:file #object[java.io.File 0x5e63cad "src/amp/core.cljs"]}
at clojure.core$ex_info.invokeStatic(core.clj:4617)
at cljs.compiler$compile_file$fn__3147.invoke(compiler.cljc:1406)
at cljs.compiler$compile_file.invokeStatic(compiler.cljc:1376)
at cljs.closure$compile_file.invokeStatic(closure.clj:430)
at cljs.closure$fn__4204.invokeStatic(closure.clj:497)
at cljs.closure$fn__4204.invoke(closure.clj:493)
at cljs.closure$fn_4146$G4139_4153.invoke(closure.clj:389)
at cljs.closure$compile_sources$iter_43154319$fn_4320.invoke(closure.clj:829)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:688)
at clojure.core$next__4341.invokeStatic(core.clj:64)
at clojure.core$dorun.invokeStatic(core.clj:3033)
at clojure.core$doall.invokeStatic(core.clj:3039)
at cljs.closure$compile_sources.invokeStatic(closure.clj:826)
at cljs.closure$build.invokeStatic(closure.clj:1942)
at cljs.build.api$build.invokeStatic(api.clj:198)
at cljs.build.api$build.invoke(api.clj:187)
at cljs.build.api$build.invokeStatic(api.clj:190)
at cljs.build.api$build.invoke(api.clj:187)
at user$eval24.invokeStatic(build.clj:3)
at user$eval24.invoke(build.clj:3)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.load(Compiler.java:7379)
... 11 more
Caused by: clojure.lang.ExceptionInfo: No method in multimethod 'parse' for dispatch value: & at line 5 src/amp/core.cljs {:file "src/amp/core.cljs", :line 5, :column 1, :tag :cljs/analysis-error}
at clojure.core$ex_info.invokeStatic(core.clj:4617)
at cljs.analyzer$error.invokeStatic(analyzer.cljc:628)
at cljs.analyzer$analyze_seq_STAR__wrap.invokeStatic(analyzer.cljc:2871)
at cljs.analyzer$analyze_seq.invokeStatic(analyzer.cljc:2892)
at cljs.analyzer$analyze_form.invokeStatic(analyzer.cljc:3011)
at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3056)
at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3073)
at cljs.compiler$emit_source.invokeStatic(compiler.cljc:1255)
at cljs.compiler$compile_file_STAR_$fn__3124.invoke(compiler.cljc:1325)
at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1159)
at cljs.compiler$compile_file_STAR_.invokeStatic(compiler.cljc:1316)
at cljs.compiler$compile_file$fn__3147.invoke(compiler.cljc:1396)
... 34 more
Caused by: java.lang.IllegalArgumentException: No method in multimethod 'parse' for dispatch value: &
at clojure.lang.MultiFn.getFn(MultiFn.java:156)
at clojure.lang.MultiFn.invoke(MultiFn.java:251)
at cljs.analyzer$analyze_seq_STAR_.invokeStatic(analyzer.cljc:2867)
at cljs.analyzer$analyze_seq_STAR__wrap.invokeStatic(analyzer.cljc:2870)
... 43 more



 Comments   
Comment by Aleksander Madland Stapnes [ 16/Jan/17 1:59 AM ]

Better explanation as I can't seem to edit the description: https://gist.github.com/madstap/c77581185afa7fea8bbf2556f2d9fafe





[CLJS-1888] Seqs of PHMs and PAMs do not handle metadata correctly Created: 13/Jan/17  Updated: 13/Jan/17

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

Type: Defect Priority: Minor
Reporter: Thomas Mulvaney Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: metadata

Attachments: Text File CLJS-1888.patch    

 Description   

Metadata on parent seq ends up being passed to the next seq. Calling `empty` on a seq also ends up carrying metadata.

Examples:

(def s (with-meta (seq {:a 1 :b 2}) {:some :meta}))

(meta s) => {:some :meta} ;; Good
(meta (rest s))  => {:some :meta} ;; Bad, expected nil
(meta (next s))  => {:some :meta} ;; Bad, expected nil
(meta (empty s)) => {:some :meta} ;; Bad, expected nil





[CLJS-1453] cljs.compiler/load-libs does not preserve user expressed require order Created: 17/Sep/15  Updated: 09/Jan/17

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

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

Attachments: Text File cljs-1453-1.patch    

 Description   

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.



 Comments   
Comment by Angus Fletcher [ 09/Jan/17 5:08 PM ]

This patch changes deps in parse 'ns and parse 'ns* to be a vector, which gives us deterministic ordering in load-libs.

Comment by Angus Fletcher [ 09/Jan/17 5:36 PM ]

Patch, updated to remove whitespace changes.





[CLJS-1885] assoc should return an array-map when passed a nil collection Created: 09/Jan/17  Updated: 09/Jan/17

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

Type: Enhancement Priority: Major
Reporter: ewen grosjean Assignee: ewen grosjean
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1885.patch    
Patch: Code




[CLJS-1884] Give a chance to MetaFn to be removed by closure under :advanced optimization Created: 09/Jan/17  Updated: 09/Jan/17

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

Type: Enhancement Priority: Major
Reporter: ewen grosjean Assignee: ewen grosjean
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1884.patch    
Patch: Code




[CLJS-1883] Foreign libs can't be found on Node.js Created: 04/Jan/17  Updated: 09/Jan/17  Resolved: 09/Jan/17

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

Type: Defect Priority: Major
Reporter: Roman Scherer Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1883.patch    

 Description   

Since CLJS-1718 foreign libs are placed under their relative path, but still loaded from the root when using Node.js.



 Comments   
Comment by Roman Scherer [ 04/Jan/17 10:20 AM ]

David, this patch uses util/relative-name instead of util/get-name when emitting the cljs.core.load_file instruction. I believe it's the same function used to place the foreign libs into the output directory. I also changed some of my previously written tests to use io/file instead of the hardcoded file separator.

Comment by David Nolen [ 09/Jan/17 11:47 AM ]

fixed https://github.com/clojure/clojurescript/commit/8e183ba8ad3eefea75c127a5fdb76c2925b809f0





[CLJS-1882] Constant table dependency order issue with Google Closure modules Created: 30/Dec/16  Updated: 04/Jan/17  Resolved: 04/Jan/17

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

Type: Defect Priority: Major
Reporter: Roman Scherer Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1882.patch    

 Description   

When compiling ClojureScript code with :optimize-constants keywords and symbols will be instantiated in the constants_table.js file and referenced from other namespaces. This is an optimization to avoid instantiating the same keyword/symbol twice. However, care must be taken that a keyword or symbol is actually instantiated before being used as a reference. This means that constants_table.js must be before any namespace using a keyword or symbol when sorting sources in dependency order. At the moment there are 2 code paths for this, one that doesn't use :modules, and one that does.

The code path without :modules sorts the dependencies in Clojure and makes sure constants_table.js comes directly after cljs.core. It uses information from parse-ns and adds a "virtual" :requires dependency.
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L727
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L3303

The code path with :modules uses Google Closure to sort the dependencies. Google Closure doesn't use the same information as the code path above. It looks only at the goog.require and goog.provide statements of the provided files and sorts them accordingly. At which place constants_table.js lands in the sorted list is not deterministic, because information about the dependencies is missing.

The missing information is the knowledge about which namespace uses a keyword or symbol from constants_table.js. If a namespace uses a keyword or symbol from the constants table it needs to require it, otherwise not.

The attached is a first draft adding a goog.provide to the constants table file and a goog.require to all other namespaces except cljs.core.



 Comments   
Comment by Roman Scherer [ 30/Dec/16 4:53 PM ]

If we go the direction emitting the information about dependencies regarding the constant table in the source files we should move the constants_table.js file name namespace under the cljs.core namespace to avoid conflicts. I would suggest clojure.core.constants or clojure.core.constants-table.

I think we could also remove code in the first code path that does the special handling at the moment. If all files correctly declare their dependencies parse-ns and Google Closure work the same way. They both parse the ns form an find out the dependency order from there. No special injections like this:
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L3303

The attached patch adds a goog.require for the constants table to every ClojureScript file at the moment, except cljs.core. This could be avoided if information about which namespace uses a keyword or symbol is available when code is emitted.

Thoughts?

Comment by Roman Scherer [ 31/Dec/16 6:33 AM ]

David, I updated the patch to use the cljs.core.constants namespace and added a test.

Comment by Roman Scherer [ 31/Dec/16 6:35 AM ]

I also realized that parse-ns and Google Closure can't share logic. The parse-ns fn parses ClojureScript files, Google Closure JavaScript files. So the middle section of my first comment is not relevant.

Comment by David Nolen [ 02/Jan/17 7:33 PM ]

The patch mostly looks good. However a small nitpick, we shouldn't be requiring the constants namespace unless we're compiling with that option enabled.

Comment by Roman Scherer [ 03/Jan/17 3:01 AM ]

David, there's a check for (-> @env/compiler :options :emit-constants) around the form that emits the goog.require for the constants table. Did you miss that, or do you want something else?

Comment by David Nolen [ 03/Jan/17 9:58 AM ]

Roman, I did miss that. Thanks!

Comment by David Nolen [ 04/Jan/17 6:47 AM ]

fixed https://github.com/clojure/clojurescript/commit/12c805f7417f39135d2b36985cf2cda98a08fe40





[CLJS-1574] CLJS string equivalence is very slow in Chrome Created: 16/Feb/16  Updated: 03/Jan/17

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

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

Google Chrome 48.0.2564.109 on Mac OS X 10.11.3
Safari 9.0.3 (11601.4.4) on Mac OS X 10.11.3



 Description   

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.

Google Chrome
js equiv:  0.005 seconds
cljs equiv:  1.898 seconds
Safari
js equiv:  0.005 seconds
cljs equiv:  0.006 seconds
(def size (* 128 1024))

(defn now []
  (.getTime (js/Date.)))

(defn delta [b a]
  (str (/ (- b a) 1000) " seconds"))

(deftest test-js-eq-perf
  (let [str1  (apply str (repeat size "a"))
        str2  (apply str (repeat size "a"))
        start (now)
        _     (is (js* "~{} == ~{}" str1 str2)
                  "js equivalence")
        end   (now)
        ]
    (println "js equiv: " (delta end start))))

(deftest test-cljs-eq-perf
  (let [str1  (apply str (repeat size "a"))
        str2  (apply str (repeat size "a"))
        start (now)
        _     (is (= str1 str2)
                  "cljs equivalence")
        end   (now)
        ]
    (println "cljs equiv: " (delta end start))))


 Comments   
Comment by Stephen Nelson [ 16/Feb/16 6:06 PM ]

This bug only occurs when cljs.pprint has been required.

Comment by Stephen Nelson [ 16/Feb/16 6:38 PM ]

After a whole lot of binary search, here's a minimal reproduction. When cljs.pprint is loaded it constructs write-option-table. It seems that constructing a hash map with the keys :added and :ns causes a call to (= :added :ns), which is sufficient to cause string equality to become extremely slow.

(ns hello-world.core)

(enable-console-print!)

(def size (* 128 1024))

(defn now []
  (.getTime (js/Date.)))

(defn delta [b a]
  (str (/ (- b a) 1000) " seconds"))

(defn test [] 
  (let [str1  (apply str (repeat size "a"))
        str2  (apply str (repeat size "a"))
        start (now)
        _     (= str1 str2)
        end   (now)
        ]
      (println "cljs equiv: " (delta end start))))

(test)

(= :added :ns)

(test)
Comment by Peter Schuck [ 17/Feb/16 4:50 PM ]

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 http://swannodette.github.io/2015/03/16/optimizing-clojurescript-function-invocation/ for more information.

Comment by Stephen Nelson [ 17/Feb/16 9:06 PM ]

This happens with :advanced, :simple, 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.

Comment by Francis Avila [ 17/Feb/16 9:14 PM ]

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 performance.mark() and performance.measure() for timing, although none of this should have mattered.

Every subsequent string compare after the first -equiv-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.

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.

Comment by Francis Avila [ 18/Feb/16 12:33 AM ]

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 before the polymorphic call will be very slow.

If you replace strict equality (triple-equal) with normal equality (double-equal), this issue goes away.

This is clearly a Chrome/v8 bug, but I'm not sure where to report it.

Minimal pure-javascript reproduction:

function str(size) {
  var s = "";
  for (var i = 0; i < size; i++) s += "a";
  return s;
}

function eq(x, y) {
  performance.mark("start");
  x === y; // No slowdown if use == instead
  performance.mark("end");
}

function print_measures() {
  performance.getEntriesByType("measure")
  .forEach(entry => console.log(entry.name, entry.duration));
}

var s1 = str(64 * 1024);
var s2 = str(64 * 1024);
var 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();

Results with Chrome 48.0.2564.109 (64-bit) on a slow iMac with OS X 10.11.3

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
Comment by Francis Avila [ 22/Feb/16 3:14 AM ]

Issue added to v8: https://bugs.chromium.org/p/v8/issues/detail?id=4773

Comment by Francis Avila [ 03/Jan/17 9:23 AM ]

Update: This bug was fixed upstream today, so it should start showing up in releases eventually.





[CLJS-1853] Docstrings are included in compiled output Created: 15/Nov/16  Updated: 02/Jan/17  Resolved: 02/Jan/17

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.293
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Richard Newman Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1853.patch    
Patch: Code

 Description   

Looking at code compiled with 'advanced':

$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$STAR_print_base_STAR$$) ? $cljs$pprint$STAR_print_base_STAR$$.$cljs$lang$test$ : null]))]);

...

$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$STAR_print_right_margin_STAR$$) ? $cljs$pprint$STAR_print_right_margin_STAR$$.$cljs$lang$test$ :

It looks like docstrings aren't stripped from dynamic vars, only from functions.

This is a bit of a waste of space...



 Comments   
Comment by António Nuno Monteiro [ 21/Dec/16 7:42 AM ]

I'm not seeing this behavior. Can you provide a minimal repro which exhibits the bug you're seeing?

Comment by Richard Newman [ 01/Jan/17 9:39 AM ]

Here's a repro case.

https://github.com/rnewman/cljs-1853

Comment by António Nuno Monteiro [ 01/Jan/17 11:15 AM ]

After some investigation, the issue seems unrelated to the description of this ticket.

Specifically, the problem occurs because there's a map which refers to Vars directly. See:
https://github.com/clojure/clojurescript/blob/95fd110f55c57b890422763ed8f2644cfbf159de/src/main/cljs/cljs/pprint.cljs#L692

Comment by Richard Newman [ 01/Jan/17 2:55 PM ]

Feel free to rename the ticket to "Required library code that includes a map that refers to vars that have associated metadata results in that metadata appearing in the compiled output, regardless of whether the metadata is ever accessed".

From an optimization perspective, I regard this behavior (however you'd like to characterize it!) as a bug — code that simply requires and uses 'cljs.pprint' ends up, when compiled at any optimization level, containing a pile of unused verbose English strings.

Comment by Richard Newman [ 01/Jan/17 2:57 PM ]

It seems like an easy 'fix' for this specific issue is to just delete `write-option-table` entirely — it's private and unused. But I don't see why `write-option-table` wouldn't be discarded by the compiler or the optimizer, and even if it exists I don't see why unused metadata wouldn't be stripped. So perhaps that's three bugs of varying specificity, each of which would make ClojureScript a little bit more production-ready.

Comment by António Nuno Monteiro [ 02/Jan/17 11:11 AM ]

Attached a patch commenting out the `cljs.pprint/write-option-table` map, as per the Slack discussion.

Comment by David Nolen [ 02/Jan/17 7:31 PM ]

fixed https://github.com/clojure/clojurescript/commit/08b5d185b616d309a5dd8cb25e5c08d59d2f5005





[CLJS-1877] :foreign-libs entries should be allowed to specify directories along with individual files Created: 21/Dec/16  Updated: 30/Dec/16

Status: In Progress
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.293
Fix Version/s: Next

Type: Enhancement Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 1
Labels: None





[CLJS-1811] Can't compose cljs.spec.test.instrument (or cljs.spec.test.check) with cljs.spec.test.enumerate-namespace Created: 05/Oct/16  Updated: 30/Dec/16

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

Type: Defect Priority: Major
Reporter: JR Heard Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Clojurescript 1.9.229



 Description   

When I call

(stest/instrument
  (stest/enumerate-namespace 'my.ns))

I get a stack trace that includes a message like `Caused by: java.lang.RuntimeException: No such namespace: stest`.

The same thing happens when I call

(stest/check
  (stest/enumerate-namespace 'my.ns))


 Comments   
Comment by JR Heard [ 05/Oct/16 5:29 PM ]

(I'm still a newbie here, please let me know if there's any more information I can provide!)

Comment by David Nolen [ 16/Dec/16 2:36 PM ]

Thanks for the report will take a look at this.

Comment by David Nolen [ 30/Dec/16 2:23 PM ]

After some consideration I now think that the Clojure enumerate-namespace helper isn't a good fit and will be unnecessarily challenging to implement in the same way. syntax-quote does not try to qualify symbols with periods in them, perhaps we should just rely on this behavior.





[CLJS-1838] cljs.compiler.api/compile-root doesn't use .cljc/.cljs precedence rules correctly. Created: 03/Nov/16  Updated: 30/Dec/16  Resolved: 30/Dec/16

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

Type: Defect Priority: Minor
Reporter: Mike Kaplinskiy Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

When you have both a .cljc and a .cljs for the same namespace, compile-root seems to arbitrarily choose which gets compiled. Case-in-point: cljs.test.



 Comments   
Comment by António Nuno Monteiro [ 05/Nov/16 9:29 AM ]

What ClojureScript version was this tested against? It would seem to me that CLJS-1772 fixed this issue (which was shipped in 1.9.229).

Comment by Mike Kaplinskiy [ 29/Dec/16 3:48 PM ]

Indeed the latest cljs fixes the issue.





[CLJS-1879] optimize cljs.core/str macro Created: 22/Dec/16  Updated: 29/Dec/16  Resolved: 29/Dec/16

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

Type: Defect Priority: Major
Reporter: Thomas Heller Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File str-perf.patch    
Patch: Code

 Description   

Currently the cljs.core/str macro generates direct calls to the cljs.core/str function via a js* inlined call. This means that it never directly dispatches to the correct arity although we know know that it is 1.

This has performance cost and prevents dead code elimination through closure.

The added patch changes the macro to directly dispatch to the correct function instead, yielding improved performance and making it dead code removable.

Also added a benchmark which is a bit useless when run with :advanced as it is removed but still useful for the future I guess.



 Comments   
Comment by Thomas Heller [ 22/Dec/16 12:13 AM ]

Benchmark on node (bstr was a temp namespace that just had the new macro)

;;; str
[], (str 1), 1000000 runs, 55 msecs
[], (str nil), 1000000 runs, 39 msecs
[], (str "1"), 1000000 runs, 44 msecs
[], (str "1" "2"), 1000000 runs, 257 msecs
[], (str "1" "2" "3"), 1000000 runs, 334 msecs

;;; bstr
[], (bstr/str 1), 1000000 runs, 13 msecs
[], (bstr/str nil), 1000000 runs, 8 msecs
[], (bstr/str "1"), 1000000 runs, 11 msecs
[], (bstr/str "1" "2"), 1000000 runs, 173 msecs
[], (bstr/str "1" "2" "3"), 1000000 runs, 210 msecs
Comment by Thomas Heller [ 22/Dec/16 12:18 AM ]

http://dev.clojure.org/jira/browse/CLJS-890

Has a lot of history on the topic and there are still some more issues that could be optimized, but this is easily the biggest gain with no real downside.

Comment by David Nolen [ 22/Dec/16 8:28 AM ]

Nice!

Comment by David Nolen [ 29/Dec/16 3:20 PM ]

fixed https://github.com/clojure/clojurescript/commit/cb66c277fc869ab9a5892cfb9ce6d1d0121d3dc7





[CLJS-1878] Use some? over (not (nil %)) in analyzer Created: 21/Dec/16  Updated: 29/Dec/16  Resolved: 29/Dec/16

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

Type: Enhancement Priority: Minor
Reporter: Ambrose Bonnaire-Sergeant Assignee: Ambrose Bonnaire-Sergeant
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File some.patch    

 Description   

I did a pass over analyzer.cljc and updated some of the branching idioms to propagate ^boolean tags using `some?` instead of `(not (nil? %))`. I also carefully added some extra `some?` or `true?` tests to propagate more ^boolean tags.



 Comments   
Comment by David Nolen [ 29/Dec/16 3:19 PM ]

fixed https://github.com/clojure/clojurescript/commit/96493c74d9d49cfd00e042a13f9d287ca238187f





[CLJS-1880] Few missing boolean annotations on some hasNext method calls Created: 23/Dec/16  Updated: 29/Dec/16  Resolved: 29/Dec/16

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

Type: Enhancement Priority: Minor
Reporter: Thomas Mulvaney Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1880.patch    

 Description   

There are a few places where boolean annotations are missing on calls to `hasNext`.

Also a case in the `HashMapIter` where `seen` should be annotated.



 Comments   
Comment by David Nolen [ 29/Dec/16 3:09 PM ]

fixed https://github.com/clojure/clojurescript/commit/47fa30dd95c850aa0643aae9c274c09bc202065c





[CLJS-1881] Improve cljs.core/distinct perf by using transient map Created: 25/Dec/16  Updated: 29/Dec/16

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

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

Attachments: Text File cljs-1881-transient-in-distinct.patch    
Patch: Code

 Description   

Current implementation of cljs.core/distinct uses persistent set. This patch improves performance by ~10%-33% by using transient map instead. Mirror Clojure task CLJ-2090

10 elements
(reduce + 0 (distinct coll))     12.360220502805724 µs => 9.504153281757874 µs (-23%)
(transduce (distinct) + 0 coll)  7.689213711227641 µs => 5.3549045227207 µs (-30%)
100 elements
(reduce + 0 (distinct coll))     136.43424283765356 µs => 106.66990187713321 µs (-21%)
(transduce (distinct) + 0 coll)  73.05427319211107 µs => 48.737280701754386 µs (-33%)
1000 elements
(reduce + 0 (distinct coll))     1.1207102908277415 ms => 919.8952205882359 µs (-17%)
(transduce (distinct) + 0 coll)  677.2834912043312 µs => 482.79681467181547 µs (-28%)
10000 elements
(reduce + 0 (distinct coll))     4.777295238095228 ms => 4.3203448275862115 ms (-9%)
(transduce (distinct) + 0 coll)  2.889020114942531 ms => 2.44890487804879 ms (-15%)

Benchmarking code: https://gist.github.com/tonsky/258c3d715e6a485522f7ba5e663624fd






[CLJS-324] cljs.core/format Created: 24/Jun/12  Updated: 27/Dec/16

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

Type: Enhancement Priority: Trivial
Reporter: Gary Fredericks Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None

Attachments: Text File 0001-CLJS-324-implement-cljs.core-format-as-wrapper-for-g.patch     File goog.string.format-0.0-1913.tgz    

 Description   

Implement cljs.core/format. Make sure there is nothing in gclosure for this. I suppose we should try to emulate the jvm version as much as that makes sense?



 Comments   
Comment by Michał Marczyk [ 28/Jun/12 11:29 AM ]

GClosure does actually include a string formatter – goog.string.format. Note that that's both a non-ctor function name and the GClosure "namespace" name, so in order to use it one must require goog.string.format on top of gstring and say gstring/format (or perhaps leave out the gstring require spec and use goog.string/format – not tested, but should work).

The patch to introduce format and printf as wrappers for goog.string.format is naturally extremely simple, so here it is. Note that this particular patch must be applied on top of CLJS-328.

I have no idea how goog.string.format compares to the JVM's String/format (basic number formatting seems to work as it should in sprintf-like functions, but other than that I haven't tested it much).

Comment by David Nolen [ 29/Jun/12 10:44 AM ]

The tests fail for me with this patch applied.

Comment by David Nolen [ 29/Jun/12 11:07 AM ]

fixed, http://github.com/clojure/clojurescript/commit/8f518760a3df8b351208e97bb70270856623bb0a

Comment by David Nolen [ 11/Sep/13 5:05 PM ]

Backing this one out, goog.string.format defies advanced optimization and it provides few of the capabilities of Clojure's format - which does a lot because of java.util.Formatter. Apologies for the churn, but this is a simple thing for people to stub in themselves for the little bit of functionality it actually delivers.

Comment by Lars Bohl [ 12/Oct/13 6:33 AM ]

Uploading a slighly modified version lein-cljsbuild's "advanced" demo, to demonstrate that using goog.string.format produces a runtime error with clojurescript 0.0.1913. Run "lein ring server" and navigate to http://localhost:3000/

The code in hello.cljs shows that goog.string.toTitleCase works, but not goog.string.format.

Comment by Julien Eluard [ 12/Oct/13 6:43 AM ]

It looks like you are not requiring correctly format. See a working example here.

Comment by Lars Bohl [ 12/Oct/13 6:58 AM ]

Julent, thanks! It needs another [goog.string.format] after [goog.string :as gstring] before you can use gstring/format. hello.cljs now looks like this, and throws no exceptions: https://www.refheap.com/19693

Comment by Ikuru Kanuma [ 27/Dec/16 6:52 PM ]

Would much appreciate a DCE compliant implementation of this, as I happen to be maintaining a library that broke because of this removal.
Has anyone worked on this since?

Comment by Gary Fredericks [ 27/Dec/16 7:31 PM ]

I thought about trying to port java.util.Formatter just for fun.

I can't figure out what you mean by "DCE compliant".

Comment by Ikuru Kanuma [ 27/Dec/16 8:33 PM ]

Oh, DCE = dead code elimination.
I thought it was a common abbrev. from this mail:
https://groups.google.com/forum/#!topic/clojure-dev/URrnaU6KWQk

I would definitely send my cheers if you do decide to put in the time!





[CLJS-1497] `find` on an associative collection does not return collection key Created: 30/Nov/15  Updated: 21/Dec/16

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

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

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

 Description   

Instead find returns the passed in key. This means metadata on the key will appear to be lost. Related to CLJS-1496.



 Comments   
Comment by Rohit Aggarwal [ 15/Jun/16 3:39 PM ]

Proposed Plan

IAssociative protocol has a function called -entry-at which has been commented out. This function needs to be implemented which will return the necessary data structure, similar to the way it has been done in Clojure.

An example of its implementation for PersistentArrayMap is:

(-entry-at
 [coll k]
 (let [idx (array-map-index-of coll k)]
   (when-not (neg? idx)
     [(aget arr idx) (aget arr (inc idx))])))

We will need to implement this for all the collections which implement that protocol.

A failing test case:

(deftest test-find-meta-cljs-1497
  (let [k        [1 2 3]
        m        {:my "meta"}
        v        1
        xs       {(with-meta k m) v}
        [k' v']  (find xs k)]
    (is (= k k'))
    (is (= v v'))
    (is (= m (meta k')))))
Comment by António Nuno Monteiro [ 13/Nov/16 10:23 AM ]

Attached patch with proposed fix and tests.

Comment by Alex Miller [ 18/Nov/16 7:50 PM ]

dnolen's comment was lost here in a system migration, but he said: "The proposed patch is a breaking change for people who implement custom collections. We need a new protocol `IEntryAt` or something like this."

Comment by António Nuno Monteiro [ 21/Dec/16 9:03 AM ]

Attached an updated patch as per review comments.





[CLJS-1876] Faster PersistentVector, Subvec and ChunkedSeq reduce. Created: 19/Dec/16  Updated: 19/Dec/16

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

Type: Enhancement Priority: Minor
Reporter: Thomas Mulvaney Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: performance

Attachments: File benchmarks.cljs     Text File CLJS-1876.patch    
Patch: Code

 Description   

This patch improved the performance of the 2-arity `-reduce` of PersistentVectors as well as the 2 and 3 arity versions of `-reduce` for `Subvecs` and `ChunkedSeqs`.

For large (> 32) `Subvecs` and `ChunkedSeqs` saw a 7x speed up in V8 and up to 11x in JavascriptCore. Smaller versions saw no change.

The 2-arity version of PersistentVector `-reduce` was also improved ~4x and ~7x in V8 and JavascriptCore respectively.

In the benchmarks below all runs where (N <= 32) were run 1,000,000 times. For the larger collections 100,000 iterations were made.

PersistentVector 3-arity reduce (no code was changed)

N master (v8) patched (v8) master (jsc) patched (jsc)
0 44 44 17 19
1 121 102 29 32
2 151 133 35 37
4 219 199 50 50
8 360 336 79 79
16 606 588 130 131
32 1124 1109 243 250
100 329 338 75 76
1000 3235 3317 704 725
10000 32960 33575 7365 7316

Persistent Vector 2-arity reduce

N master (v8) patched (v8) master (jsc) patched (jsc)
0 65 41 29 12
1 96 58 49 42
2 147 66 87 45
4 246 85 113 44
8 446 142 202 69
16 829 276 362 98
32 1627 506 693 132
100 534 154 236 41
1000 5442 1568 2321 329
10000 58396 15386 26162 3406

ChunkedSeq 3-arity reduce

N master (v8) patched (v8) master (jsc) patched (jsc)
0 57 69 93 88
1 54 60 31 26
2 68 63 27 28
4 94 91 37 39
8 146 152 59 58
16 272 266 121 107
32 479 526 170 174
100 1186 165 459 39
1000 11760 1539 4547 334
10000 121986 16080 48639 3384

ChunkedSeq 2-arity reduce

N master (v8) patched (v8) master (jsc) patched (jsc)
0 62 63 96 97
1 23 31 16 19
2 35 40 20 17
4 68 70 26 29
8 116 120 49 47
16 232 223 83 89
32 467 444 156 158
100 1123 164 417 39
1000 12328 1659 4516 327
10000 126570 15940 47435 3330

Subvec 3-arity reduce

N master (v8) patched (v8) master (jsc) patched (jsc)
0 67 67 51 34
1 185 71 100 35
2 296 84 160 44
4 514 100 259 52
8 958 156 405 77
16 1878 295 733 138
32 3668 565 1433 139
100 1164 165 462 36
1000 12596 1600 4798 337
10000 122919 16108 48093 3511

Subvec 2-arity reduce

N master (v8) patched (v8) master (jsc) patched (jsc)
0 73 49 35 22
1 169 58 75 48
2 289 70 117 54
4 544 103 197 56
8 961 159 378 74
16 1852 288 697 103
32 3644 514 1425 145
100 1245 147 441 39
1000 12065 1537 4556 333
10000 122519 15600 46324 3370

The source code for the benchmarks is attached.






[CLJS-1866] RangedIterator performance tweaks Created: 08/Dec/16  Updated: 19/Dec/16

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

Type: Enhancement Priority: Minor
Reporter: Thomas Mulvaney Assignee: Thomas Mulvaney
Resolution: Unresolved Votes: 0
Labels: performance

Attachments: Text File CLJS-1866.patch     Text File CLJS-1866-updated.patch     Text File CLJS-1866-updated.patch    
Patch: Code

 Description   

The attached patch simplifies and speeds up the RangedIterator.

The benchmarks were run using the following function to test vector iteration:

(defn consume-iterator
  [v]
  (let [iter (-iterator v)]
    (loop []
      (when (.hasNext iter)
        (.next iter)
        (recur)))))

A series of "simple-benchmarks" were setup as follows:

(simple-benchmark [v (into [] (range N))] (consume-iterator v) I)

Where 'N' and 'I' were values from the 'Vector Size' and 'Iterations' columns of the table below .

Vector Size Iterations V8 Speed [msec] (master) V8 Speed [msec] (patch) JSC Speed [msec] (master) JSC Speed [msec] (patch)
1 100,000 15 11 13 7
2 100,000 14 10 7 4
4 100,000 18 10 9 5
8 100,000 27 12 14 6
16 100,000 43 17 19 9
32 100,000 74 24 37 15
100 100,000 217 59 105 45
1000 100,000 2008 524 1032 392
10,000 100,000 20390 5856 10249 4178
100,000 10,000 20334 5324 10324 4387

Javascript engine versions used:

  • V8 version 5.1.281.47
  • JSC version Unknown

The RangedIterator constructor function `ranged-iterator` was also made private.



 Comments   
Comment by David Nolen [ 16/Dec/16 2:04 PM ]

Let's get a patch with the performance change without altering the constructor first. Thanks.

Comment by Thomas Mulvaney [ 17/Dec/16 7:15 AM ]

Rebased and constructor no longer private.

Comment by David Nolen [ 17/Dec/16 9:59 AM ]

Sorry for not being clear. Leave the fields of the deftype alone even if we aren't using them for now. We want the performance enhancements without changing the API at all.

Comment by Thomas Mulvaney [ 19/Dec/16 5:58 AM ]

Thanks that makes sense. Fixed in this patch.





[CLJS-1859] Comparing a map and a record with = produces different results based on argument order Created: 23/Nov/16  Updated: 17/Dec/16  Resolved: 16/Dec/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.293
Fix Version/s: 1.9.293

Type: Defect Priority: Minor
Reporter: Juan Facorro Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None
Environment:

Mac OS X
V8
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)



 Description   

The result of comparing a map and a record is different based on the order of the arguments to =:

To quit, type: :cljs/quit 
cljs.user=> (defrecord R []) 
cljs.user/R 
cljs.user=> (= {} (R.)) 
true 
cljs.user=> (= (R.) {}) 
false 

The result is the same for the code above with tags r1.7.228, r1.8.34 and 1.9.293.

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 equiv 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.

In Clojure JVM the implementation of equiv in clojure.lang.APersistentMap checks for the marker interface clojure.lang.MapEquivalence, which avoids this situation.



 Comments   
Comment by David Nolen [ 16/Dec/16 2:18 PM ]

This is not a bug an in fact the behavior of ClojureScript is simply wrong. Records and maps are never equal in Clojure.

Comment by Juan Facorro [ 17/Dec/16 12:40 PM ]

I don't understand. If the behavior in ClojureScript is wrong, shouldn't it be fixed so that (= {} (R.)) returns to false.

Comment by David Nolen [ 17/Dec/16 6:05 PM ]

Yes but that's a different issue from what this ticket described.





[CLJS-1875] Difference in seqable? between Clojure and ClojureScript Created: 17/Dec/16  Updated: 17/Dec/16  Resolved: 17/Dec/16

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

Type: Enhancement Priority: Minor
Reporter: Arne Brasseur Assignee: Arne Brasseur
Resolution: Completed Votes: 0
Labels: None

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

 Description   

The seqable? predicate introduced in Clojure 1.9 will return true for anything that can successfully be passed to seq. This includes instances of (I)Seqable, native arrays, Java collections, and strings.

Clojure docstring: "Return true if the seq function is supported for s"

In ClojureScript seqable? only checks for (satisfies? ISeqable s)

Clojurescript docstring: "Return true if s satisfies ISeqable"

Clojure:

(seqable? (array 1 2 3)) ;;=> true
(seqable? "foo") ;;=> true

ClojureScript

(seqable? (array 1 2 3)) ;;=> false
(seqable? "foo") ;;=> false



 Comments   
Comment by Arne Brasseur [ 17/Dec/16 2:47 AM ]

This adds the same checks to seqable? that are being used in seq.

This one I wasn't sure how to test:

(native-satisfies? ISeqable s)

Comment by David Nolen [ 17/Dec/16 6:25 AM ]

You don't need `native-satisfies?`. Otherwise looks good.

Comment by Arne Brasseur [ 17/Dec/16 8:18 AM ]

Version without native-satisfies?

Comment by Arne Brasseur [ 17/Dec/16 8:19 AM ]

Thanks, I updated the patch.

Comment by David Nolen [ 17/Dec/16 9:57 AM ]

fixed https://github.com/clojure/clojurescript/commit/101d7d9e03e90518e6769781dd33fbe6387d2d44





[CLJS-1829] 3-arity get does not return not-found on negative key values for arrays and strings Created: 21/Oct/16  Updated: 17/Dec/16  Resolved: 17/Dec/16

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

Type: Defect Priority: Major
Reporter: Thomas Mulvaney Assignee: Thomas Mulvaney
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File cljs-1829.patch     Text File CLJS-1829-updated.patch    
Patch: Code and Test

 Description   

Examples of failing cases:

Calling `(get "asd" -1 :not-found)` returns nil rather than :not-found.
Calling `(get #js [1 2 3] -1 :not-found)` returns nil rather than :not-found.



 Comments   
Comment by António Nuno Monteiro [ 21/Oct/16 5:10 AM ]

Good catch. Probably related to https://github.com/clojure/clojurescript/commit/9cb8da1d82078cfe21c7f732d94115867f455a0a

Mind if I work on this?

Comment by Thomas Mulvaney [ 21/Oct/16 5:49 AM ]

The attached patch also catches the case where a key is nil. Also using charAt rather than aget for strings.

Comment by Thomas Mulvaney [ 21/Oct/16 5:50 AM ]

Sorry António, I just saw your comment.

Comment by David Nolen [ 16/Dec/16 1:51 PM ]

The patch needs to be rebased on master. Thanks.

Comment by Thomas Mulvaney [ 17/Dec/16 7:13 AM ]

Rebased.

Comment by David Nolen [ 17/Dec/16 9:55 AM ]

fixed https://github.com/clojure/clojurescript/commit/4f08dbdedb4d5645a977eb43d21a4ebf28597374





[CLJS-1823] read-string on map with multiple keys should throw error Created: 15/Oct/16  Updated: 17/Dec/16  Resolved: 17/Dec/16

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

Type: Defect Priority: Major
Reporter: Thomas Mulvaney Assignee: Thomas Mulvaney
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File cljs-1823-alt.patch     Text File CLJS-1823.patch    

 Description   

On an array-map sized string `(read-string "{:a 1 :b 2 :a 1}")` returns a map with 2 :a keys.
On a hash-map sized string with duplicates no error is thrown.

Both of these cases deviate from Clojure's behaviour which is to throw a duplicate key exception.



 Comments   
Comment by Rohit Aggarwal [ 16/Oct/16 5:22 AM ]

I am attaching a patch which makes the behaviour of reading a PersistentArrayMap same as PersistentHashMap. Now the duplicates are removed from PersistentArrayMap.

Both however don't throw an error.

Comment by Thomas Mulvaney [ 17/Oct/16 5:03 AM ]

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.

Comment by David Nolen [ 16/Dec/16 1:56 PM ]

Thomas can we get this patch without the changes to to the API? i.e. leave no-clone stuff alone.

Comment by Mike Fikes [ 16/Dec/16 7:38 PM ]

For reference, here is an example use of the no-clone stuff that would break: https://github.com/cognitect/transit-cljs/blob/master/src/cognitect/transit.cljs#L94

Comment by David Nolen [ 17/Dec/16 6:28 AM ]

I accidentally applied this one. I went ahead and removed all API level deletions and changes. Thomas, for future reference never change existing APIs. Only additions and new names. Thanks.

Comment by David Nolen [ 17/Dec/16 6:29 AM ]

fixed https://github.com/clojure/clojurescript/commit/24f4189445d802fcd3155855cf5f51e4c1902785





[CLJS-1874] Self-host: :fn-var true for macros Created: 16/Dec/16  Updated: 16/Dec/16

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

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap

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

 Description   

In self-host ClojureScript, :fn-var is unconditionally set to true for macros.

One issue this creates is for cljs.test/function?, here

https://github.com/clojure/clojurescript/blob/d1b8b31f7247688098d9e61bb33302a6edc57c2c/src/main/cljs/cljs/test.cljc#L23

in that it causes macros in is expressions, like (is (or true)) to be mis-handled
as if they were functions.

Here is a minimal repro illustrating :fn-var being set:

$ java -jar cljs.jar -m cljs.repl.node
ClojureScript Node.js REPL server listening on 52055
To quit, type: :cljs/quit
cljs.user=> (require 'cljs.js)
true
cljs.user=> (let [st (cljs.js/empty-state)]
  (cljs.js/eval-str st
    "(ns cljs.user (:require-macros foo.core))"
    nil
    {:eval    cljs.js/js-eval
     :load    (fn [_ cb]
                (cb {:lang   :clj
                     :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"}))
     :context :expr}
    (fn [_]
      (-> @st
        (get-in [:cljs.analyzer/namespaces 'foo.core$macros :defs 'add])
        (select-keys [:macro :fn-var])))))
{:macro true, :fn-var true}
cljs.user=>

Note in the repro above both :macro and :fn-var are set to true.






[CLJS-1873] Self-host: Unit tests fail owing to test.check dep Created: 16/Dec/16  Updated: 16/Dec/16

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

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap

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

 Description   

Currently the self-host unit tests fail to run with:

$ script/test-self-parity
Testing with Node
WARNING: baz is a single segment namespace at line 1 src/test/cljs/baz.cljs
#error {:message "No such namespace: cljs.test.check, could not locate cljs/test/check.cljs, cljs/test/check.cljc, or Closure namespace \"cljs.test.check\"", :data {:tag :cljs/analysis-error}}

Reason:

With https://github.com/clojure/clojurescript/commit/d1b8b31f7247688098d9e61bb33302a6edc57c2c
the cljs.spec-test namespace was revised to require the cljs.spec.test namespace, which, in turn requires the clojure.test.check namespace. (The auto-aliasing to cljs.test.check is tried an this fails, and this is the diagnostic you ultimately see.)

The port of test.check to self-hosted ClojureScript (TCHECK-105) hasn't yet been released, and, so far, the self-host tests have been avoiding the need for test.check.



 Comments   
Comment by Mike Fikes [ 16/Dec/16 7:07 PM ]

Attached patch fixes the self-test unit tests by moving the test.check-dependent portion into a test namespace for cljs.spec.test (namely cljs.spec.test-test) which is skipped in self-host tests. (When TCHECK-105 is released we can re-visit and revise the self-host test runner to load the needed source from the test check JAR that is placed in lib by script/bootstrap.





[CLJS-1831] Self-host: Improperly munge ns names Created: 22/Oct/16  Updated: 16/Dec/16

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

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap

Attachments: Text File CLJS-1831-2.patch     Text File CLJS-1831.patch    

 Description   

If you have a namespace containing a reserved JavaScript keyword, in self-hosted ClojureScript the namespace isn't properly munged for the goog.provide call. A result is that symbols defined in the namespace will be attached to a nonexistent JavaScript object.

To reproduce, add a test namespace, say static.core that does nothing but have an assert that (= 1 1).



 Comments   
Comment by Mike Fikes [ 22/Oct/16 1:04 PM ]

Without the prod code fixes in cljs.js, a new unit test fails, producing the desired warning but then tripping up on attempting to attach to an undefined JavaScript static$ object, with the root cause being a goog.provide('static.core-test') call instead of the needed goog.provide('static$.core-test') as is done in regular ClojureScript:

WARNING: Namespace static.core-test contains a reserved JavaScript keyword, the corresponding Google Closure namespace will be munged to static$.core_test at line 1 src/test/cljs/static/core_test.cljs
#error {:message "ERROR in file src/test/cljs/static/core_test.cljs", :data {:tag :cljs/analysis-error}, :cause #object[ReferenceError ReferenceError: static$ is not defined]}

The production fix is to simply call cljs.compiler/munge instead of cljs.core/munge.

Comment by Mike Fikes [ 16/Dec/16 2:50 PM ]

Previous patch no longer applies. Attaching CLJS-1831-2.patch





[CLJS-1812] cljs.spec.test.check has the side effect of instrumenting vars it's called on Created: 05/Oct/16  Updated: 16/Dec/16  Resolved: 16/Dec/16

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

Type: Defect Priority: Minor
Reporter: JR Heard Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File patch-0001.patch    

 Description   

When using (stest/check) to test a function, I noticed that calls to the function later on in my code behaved as if the function were instrumented, even though I never explicitly called (stest/instrument) on it.

I think that there's something wrong with this line: https://github.com/clojure/clojurescript/blob/7e90ad5/src/main/cljs/cljs/spec/test.cljc#L157 .

As far as I can tell from poking around at this code, re-inst# is always true, because in cljs.spec.test, calling (unstrument `foo/bar) will return [foo/bar] even if foo/bar is not currently instrumented. From what I can tell from poking around in the REPL, this is a departure from Clojure's behavior, which is to return [] in this situation.

As always, it's possible I'm insane or misinterpreting how this system is intended to behave; but for what it's worth, the print statements I've added to my local copy of Clojurescript indicate that if you call (stest/check `foo/bar) when @instrumented-vars is {}, re-inst# will be true, and `foo/bar will therefore be instrumented at the end of check's execution. This seems like it's probably a bug.



 Comments   
Comment by JR Heard [ 06/Oct/16 10:16 AM ]

I think I'd actually like to take a stab at this one, if that's all right.

Comment by JR Heard [ 06/Oct/16 3:03 PM ]

Added a patch. Let me know if I goofed in its formatting, commit message style, etc. Includes two tests that fail before this change and pass after it.

I had trouble writing the second test assertion in the way I wanted - (is (not (thrown? js/Error (h-cljs-1812 "foo")))) didn't seem to do the trick - so I ended up just calling the helper function with invalid args directly; please let me know if there's a better way

Comment by David Nolen [ 16/Dec/16 2:35 PM ]

fixed https://github.com/clojure/clojurescript/commit/d1b8b31f7247688098d9e61bb33302a6edc57c2c





[CLJS-1868] CLJS compilation error with Closure lib dependency on Windows Created: 11/Dec/16  Updated: 16/Dec/16

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

Type: Defect Priority: Minor
Reporter: Dejan Josifovic Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, cljs, compiler
Environment:

Tested on Windows 10 with java 8 and on windows 7 with java 7 and java 8.
Clojure version is 1.8.0 on both systems.


Attachments: Text File stacktrace.txt    

 Description   

I encountered this error while developing a cljs project that included openlayers lib in its deps.
Open layers is a Closure library and I used the latest version 3.15.1.

The error that compiler reports is:
java.io.IOException: The filename, directory name, or volume label syntax is incorrect

I have recreated the minimal scenario, the one like on ClojureScript Quick start guide.
Steps to reproduce the problem (basically like the quick start):

  • Download standalone cljs jar from the link in the guide
  • Create the same build.cljs file as defined on the guide
  • Download openlayers-3.15.1.jar and place it in the root
  • Add require statement in core.cljs - (ns hello-world.core (:require ol.Map)) for example
  • Than in cmd run java -cp "cljs.jar;openlayers-3.15.1.jar;src" clojure.main build.clj

I have also tested with cljs master branch (created an uberjar and tested again) and i get the same error.

Attached is the example stacktrace (in that run I added :verbose true to get the 'Copying...' output).



 Comments   
Comment by Dejan Josifovic [ 11/Dec/16 8:06 AM ]

I have also created a git hub repo for this problem: https://github.com/28/openlayers-cljs-compile-error-repo

Comment by Gijs Stuurman [ 12/Dec/16 4:22 AM ]

This issue is present on all OS's, but breaks on Windows. I see it on Ubuntu.

The logic that already exists to shorten filenames for files from jars is not applied for the library in the openlayer.jar.

In verbose mode there is this output:

Copying jar:file:/path/openlayers/openlayers-cljs-compile-error-repo/openlayers-3.15.1.jar!/cljsjs/openlayers/development/ol/events/event.js to out/file:/path/openlayers/openlayers-cljs-compile-error-repo/openlayers-3.15.1.jar!/cljsjs/openlayers/development/ol/events/event.js

The file that gets written into the "out" directory contains a colon (:) and an exclamation point (!) in the path (at the "file:" and "jar!"). On Windows this is a Java IO Exception, because colons are not allowed in file names or paths.

The generated "main.js" file contains:

goog.addDependency("../file:/path/openlayers/openlayers-cljs-compile-error-repo/openlayers-3.15.1.jar!/cljsjs/openlayers/development/ol/events/event.js", ['ol.events.Event'], []);

The "openlayers" jar is a Google Closure compatible JavaScript library in a jar. All its files have a "goog.provides" and "goog.require"'s and the jar contains a "deps.cljs" with the keys :libs and :externs.

The following monkey patch in "build.clj" makes paths without "file:" or "jar!" in them:

(alter-var-root #'cljs.closure/rel-output-path
                (fn [orig-fn]
                  (fn [js & args]
                    (apply orig-fn (dissoc js :closure-lib) args))))

For comparison, the verbose output for the files generated for files from cljs.jar:

Copying jar:file:/path/openlayers/openlayers-cljs-compile-error-repo/cljs.jar!/goog/base.js to out/goog/base.js
Comment by David Nolen [ 12/Dec/16 9:25 AM ]

Gijs thanks for the additional information. Very helpful, will take a look.

Comment by David Nolen [ 16/Dec/16 2:02 PM ]

The suggested fix isn't desirable as far as I can tell since we have a branch specifically for dealing with Closure libs that will be avoided. We need a better explanation.





[CLJS-1786] Add knob for controlling printing of namespaced maps Created: 21/Sep/16  Updated: 16/Dec/16  Resolved: 16/Dec/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.293
Fix Version/s: None

Type: Task Priority: Major
Reporter: David Nolen Assignee: Lauri Oherd
Resolution: Completed Votes: 0
Labels: newbie

Attachments: Text File CLJS-1786.patch    

 Description   

See these Clojure commits:

https://github.com/clojure/clojure/commit/d57b5559829be8e8b3dcb28a20876b32615af0cb
https://github.com/clojure/clojure/commit/b49c1984a1527d17951fbb23ddf9406805a1343f
https://github.com/clojure/clojure/commit/05a8e8b323042fa043355b716facaed6003af324



 Comments   
Comment by Lauri Oherd [ 28/Sep/16 4:30 PM ]

Added print-namespace-maps flag for controlling printing of namespaced maps.
Unlike in Clojure repl the default value is false in Clojurescript repl.
Please comment if this needs to be fixed.

Comment by David Nolen [ 28/Sep/16 4:44 PM ]

Why should the default be different from Clojure?

Comment by Lauri Oherd [ 06/Oct/16 10:59 AM ]

I couldn't figure out initially how to set the print-namespace-maps value to true only in repl environment.
This is resolved in an updated patch. Please check if the implementation is acceptable - in file src/main/clojure/cljs/repl.cljc line 558 the following statement is executed: (set! cljs.core.print-namespace-maps true)

Comment by António Nuno Monteiro [ 06/Oct/16 11:05 AM ]

I don't think that's the desired approach for `print-namespace-maps` to work in every REPL. The wrap-fn is not used for every REPL, as custom REPLs may specify their own.

Why don't you bind the dynamic variable where all others are being bound?

Comment by Lauri Oherd [ 06/Oct/16 1:20 PM ]

Thank you for reviewing the previous patch and suggesting a better approach, António! Updated the patch with suggested solution.

Comment by David Nolen [ 16/Dec/16 1:59 PM ]

fixed https://github.com/clojure/clojurescript/commit/95fd110f55c57b890422763ed8f2644cfbf159de





[CLJS-1836] nth doesn't throw for IndexedSeqs Created: 25/Oct/16  Updated: 16/Dec/16  Resolved: 16/Dec/16

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

Type: Defect Priority: Major
Reporter: Thomas Mulvaney Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File cljs-1836.patch    
Patch: Code and Test

 Description   

Examples:

(nth (seq (array 0 1 2 3)) 4) => nil (expected js/Error)
(nth (seq (array 0 1 2 3)) -1) => nil (expected js/Error)
(nth (seq [0 1 2 3]) 4 :not-found) => nil (expected :not-found)
(nth (seq [0 1 2 3]) -1 :not-found) => nil (expected :not-found)

This only affects sequences of javascript arrays, strings and small (<= 32 elements) PersistentVectors.



 Comments   
Comment by David Nolen [ 16/Dec/16 1:49 PM ]

fixed https://github.com/clojure/clojurescript/commit/3b3db232711266f9f41c94c777084664d6d0b71b





[CLJS-1872] Remove warnings from (:require [foo :refer-macros [bar]) when (:require-macros [foo :refer [bar]) works Created: 14/Dec/16  Updated: 15/Dec/16  Resolved: 15/Dec/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.293
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Greg Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: warning
Environment:

macOSX Sierra, and Ubuntu 16.04, but I suspect its platform independent.



 Description   

Both ns forms

(:require [foo :refer-macros [read-file])
and
(:require-macros [foo :refer [read-file])

work, but the :require form raises a WARNING: Use of undeclared Var cljs.core/slurp at line 5 src/pairwise/cljsmacros.cljc

where cljsmacros contains

(defmacro read-file [file]
(clojure.core/slurp file))



 Comments   
Comment by António Nuno Monteiro [ 14/Dec/16 10:11 AM ]

Not sure this is a bug. `slurp` is not in `cljs.core`, which is why you get the warning.

Comment by David Nolen [ 15/Dec/16 9:32 AM ]

not an issue





[CLJS-1871] A declare with :arglists should generate static function calls Created: 14/Dec/16  Updated: 14/Dec/16

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

Type: Enhancement Priority: Minor
Reporter: A. R Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: performance


 Description   

This is performance enhancement.

  1. Problem
    After a declare the compiler doesn't know which arities the function will be defined with and hence generates code that checks if that arity is defined and then either calls it or uses a slower `xy-fn.call(null, ...)` construct. This is not optimal since it can be slower and also generates slightly more code.

Especially functions which only have one arity are problematic since they will end up being called with `xy-fn.call`.

  1. Affects
    Code that uses a function that was only declared and not def'ed yet. Such as `cons` in `IndexedSeq` or `conj!` in `TransientHashMap`.
    1. Performance
      A preliminary benchmark showed neglible improvements in Chrome v54 but a significant (factor of 2.2) performance benefit in Firefox.
  1. Solution
    Most of the declares should use `(def ^{:declare true, :arglists '([x xs])} cons)` and the compiler should take the `:arglists` into consideration and emit direct function calls instead.





[CLJS-1870] Quoted specs check in require macro symbols Created: 11/Dec/16  Updated: 13/Dec/16  Resolved: 13/Dec/16

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

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

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

 Description   

If you use the new require macro and fail to quote the lib specs, it will indicate such. But the check will derail for a symbol lib spec.

For example: (require [clojure.set]) causes a diagnostic: "Arguments to require must be quoted. Offending spec: [clojure.set]".
On the other hand: (require clojure.set) doesn't produce the expected diagnostic, but derails with "Don't know how to create ISeq from: clojure.lang.Symbol".



 Comments   
Comment by David Nolen [ 13/Dec/16 1:05 PM ]

fixed https://github.com/clojure/clojurescript/commit/cfbaba0f7f2f9f918896528ca8e814831218458b





[CLJS-1869] Regression importing goog.Uri Created: 11/Dec/16  Updated: 13/Dec/16  Resolved: 13/Dec/16

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

Type: Defect Priority: Major
Reporter: Mike Fikes Assignee: António Nuno Monteiro
Resolution: Completed Votes: 0
Labels: None

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

 Description   

With the latest release, a regression was introduced which breaks importing goog.Uri.

To repro, download the released cljs.jar and then

$ java -jar cljs.jar -m cljs.repl.node
ClojureScript Node.js REPL server listening on 56132
To quit, type: :cljs/quit
cljs.user=> *clojurescript-version*
"1.9.293"
cljs.user=> (import 'goog.Uri)
nil
cljs.user=> (Uri. "http://example.com")
WARNING: Use of undeclared Var cljs.user/Uri at line 1 <cljs repl>
WARNING: Use of undeclared Var cljs.user/Uri at line 1 <cljs repl>
TypeError: cljs.user.Uri is not a constructor
    at repl:1:90
    at repl:9:3
    at repl:14:4
    at ContextifyScript.Script.runInThisContext (vm.js:26:33)
    at Object.exports.runInThisContext (vm.js:79:17)
    at Domain.<anonymous> ([stdin]:50:34)
    at Domain.run (domain.js:221:14)
    at Socket.<anonymous> ([stdin]:49:25)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)

For reference, here is it working with the previous release:

$ java -jar cljs.jar -m cljs.repl.node
ClojureScript Node.js REPL server listening on 55926
To quit, type: :cljs/quit
cljs.user=> *clojurescript-version*
"1.9.230"
cljs.user=> (import 'goog.Uri)
nil
cljs.user=> (Uri. "http://example.com")
#object[Object http://example.com]
cljs.user=> (.getScheme *1)
"http"


 Comments   
Comment by Mike Fikes [ 11/Dec/16 4:52 PM ]

Hey António, assigning over to you for a patch review to see if you have any views on the attached.

Comment by Mike Fikes [ 11/Dec/16 5:48 PM ]

António pointed out that canonicalize-specs was likely not defective as it was preserved in the revisions. The root cause appears to be that the original REPL code did not call canonicalize-specs for its import REPL special, but instead had applied a somewhat simpler canonicalization function literal for that case.

Attaching a second revision patch that introduces a new canonicalize-import-specs that is faithful to the original REPL code and also as a benefit re-adds support for doing things like (import '(goog.Uri)).

Comment by David Nolen [ 13/Dec/16 1:01 PM ]

fixed https://github.com/clojure/clojurescript/commit/3ca51dc947de98b9b83949356e30ecd307bc5088





[CLJS-1653] cljs.spec: keys* causes exception Created: 29/May/16  Updated: 13/Dec/16  Resolved: 29/Jul/16

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

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

Attachments: Text File CLJS-1653-2.patch     Text File CLJS-1653.patch    
Patch: Code

 Description   

From https://clojure.org/guides/spec there is a keys* usage in the Entity Maps section. If tried with cljs.spec an exception is thrown:

cljs.user=> (require '[cljs.spec :as s])
nil
cljs.user=> (s/def ::server (s/keys* :req [::id ::host] :opt [::port]))
clojure.lang.ExceptionInfo: No method in multimethod 'parse' for dispatch value: & at line 1 <cljs repl> {:file "<cljs repl>", :line 1, :column 17, :tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4617)
	at clojure.core$ex_info.invoke(core.clj:4617)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:580)
	at cljs.analyzer$error.invoke(analyzer.cljc:576)
	at cljs.analyzer$analyze_seq_STAR__wrap.invokeStatic(analyzer.cljc:2420)
	at cljs.analyzer$analyze_seq_STAR__wrap.invoke(analyzer.cljc:2419)
	at cljs.analyzer$analyze_seq.invokeStatic(analyzer.cljc:2442)
	at cljs.analyzer$analyze_seq.invoke(analyzer.cljc:2423)
	at cljs.analyzer$analyze_form.invokeStatic(analyzer.cljc:2555)
	at cljs.analyzer$analyze_form.invoke(analyzer.cljc:2551)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:2602)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:2593)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:2618)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:2605)
	at cljs.analyzer$analyze_seq.invokeStatic(analyzer.cljc:2443)
	at cljs.analyzer$analyze_seq.invoke(analyzer.cljc:2423)
	at cljs.analyzer$analyze_form.invokeStatic(analyzer.cljc:2555)
	at cljs.analyzer$analyze_form.invoke(analyzer.cljc:2551)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:2602)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:2593)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:2618)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:2605)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:2613)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:2605)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:2612)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:2605)
	at cljs.analyzer$parse_invoke_STAR_$ana_expr__2106.invoke(analyzer.cljc:2257)
	at clojure.core$map$fn__4785.invoke(core.clj:2646)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.Cons.next(Cons.java:39)
	at clojure.lang.PersistentVector.create(PersistentVector.java:73)
	at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:44)
	at clojure.core$vec.invokeStatic(core.clj:377)
	at clojure.core$vec.invoke(core.clj:367)
	at cljs.analyzer$parse_invoke_STAR_.invokeStatic(analyzer.cljc:2264)
	at cljs.analyzer$parse_invoke_STAR_.invoke(analyzer.cljc:2235)
	at cljs.analyzer$parse_invoke.invokeStatic(analyzer.cljc:2273)
	at cljs.analyzer$parse_invoke.invoke(analyzer.cljc:2271)
	at cljs.analyzer$analyze_seq_STAR_.invokeStatic(analyzer.cljc:2417)
	at cljs.analyzer$analyze_seq_STAR_.invoke(analyzer.cljc:2414)
	at cljs.analyzer$analyze_seq_STAR__wrap.invokeStatic(analyzer.cljc:2421)
	at cljs.analyzer$analyze_seq_STAR__wrap.invoke(analyzer.cljc:2419)
	at cljs.analyzer$analyze_seq.invokeStatic(analyzer.cljc:2442)
	at cljs.analyzer$analyze_seq.invoke(analyzer.cljc:2423)
	at cljs.analyzer$analyze_form.invokeStatic(analyzer.cljc:2555)
	at cljs.analyzer$analyze_form.invoke(analyzer.cljc:2551)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:2602)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:2593)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:2618)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:2605)
	at cljs.analyzer$analyze_seq.invokeStatic(analyzer.cljc:2443)
	at cljs.analyzer$analyze_seq.invoke(analyzer.cljc:2423)
	at cljs.analyzer$analyze_form.invokeStatic(analyzer.cljc:2555)
	at cljs.analyzer$analyze_form.invoke(analyzer.cljc:2551)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:2602)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:2593)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:2618)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:2605)
	at cljs.repl$evaluate_form.invokeStatic(repl.cljc:450)
	at cljs.repl$evaluate_form.invoke(repl.cljc:440)
	at cljs.repl$eval_cljs.invokeStatic(repl.cljc:570)
	at cljs.repl$eval_cljs.invoke(repl.cljc:563)
	at cljs.repl$repl_STAR_$read_eval_print__6148.invoke(repl.cljc:875)
	at cljs.repl$repl_STAR_$fn__6154$fn__6163.invoke(repl.cljc:914)
	at cljs.repl$repl_STAR_$fn__6154.invoke(repl.cljc:913)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1154)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1145)
	at cljs.repl$repl_STAR_.invokeStatic(repl.cljc:877)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:761)
	at cljs.repl$repl.invokeStatic(repl.cljc:995)
	at cljs.repl$repl.doInvoke(repl.cljc:925)
	at clojure.lang.RestFn.invoke(RestFn.java:410)
	at user$eval6335.invokeStatic(NO_SOURCE_FILE:3)
	at user$eval6335.invoke(NO_SOURCE_FILE:3)
	at clojure.lang.Compiler.eval(Compiler.java:6927)
	at clojure.lang.Compiler.eval(Compiler.java:6890)
	at clojure.core$eval.invokeStatic(core.clj:3105)
	at clojure.main$eval_opt.invokeStatic(main.clj:288)
	at clojure.main$eval_opt.invoke(main.clj:282)
	at clojure.main$initialize.invokeStatic(main.clj:308)
	at clojure.main$null_opt.invokeStatic(main.clj:342)
	at clojure.main$null_opt.invoke(main.clj:339)
	at clojure.main$main.invokeStatic(main.clj:421)
	at clojure.main$main.doInvoke(main.clj:384)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: No method in multimethod 'parse' for dispatch value: &
	at clojure.lang.MultiFn.getFn(MultiFn.java:156)
	at clojure.lang.MultiFn.invoke(MultiFn.java:251)
	at cljs.analyzer$analyze_seq_STAR_.invokeStatic(analyzer.cljc:2416)
	at cljs.analyzer$analyze_seq_STAR_.invoke(analyzer.cljc:2414)
	at cljs.analyzer$analyze_seq_STAR__wrap.invokeStatic(analyzer.cljc:2421)
	... 85 more


 Comments   
Comment by Mike Fikes [ 30/May/16 10:55 AM ]

The attached patch works around the issue by qualifying the reference to cljs.spec/&.

With it, the example in the docstring works:

(s/conform (s/cat :i1 integer? :m (s/keys* :req-un [::a ::c]) :i2 integer?) [42 :a 1 :c 2 :d 4 99])
{:i1 42, :m {:a 1, :c 2, :d 4}, :i2 99}

(There is probably a more correct solution that probably involves changing the analyzer, which would lead to users being able to refer & and use it as (& ...), but this patch would get us by for now if desired.)

Comment by Mike Fikes [ 27/Jul/16 10:05 AM ]

Original patch no longer applies; attaching CLJS-1653-2.patch.

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

fixed https://github.com/clojure/clojurescript/commit/5a78c9fb881f08b1f9578f9cd9dd265bbdd5c720

Comment by Stanislav Gurenkov [ 12/Dec/16 6:02 PM ]

Still getting this error, looks like patch was not merged properly.

Comment by David Nolen [ 13/Dec/16 12:59 PM ]

Thanks fixed in the master.





[CLJS-1461] Convert analyzer to conform to tools.analyzer's spec Created: 28/Sep/15  Updated: 12/Dec/16

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

Type: Enhancement Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: Ambrose Bonnaire-Sergeant
Resolution: Unresolved Votes: 6
Labels: None


 Description   

tools.analyzer has a handy common AST format for map-based analysis results. We should use this format in the ClojureScript analyzer so tooling that already accepts this format can work seamlessly with ClojureScript.

Work in progress: https://github.com/frenchy64/clojurescript/tree/reflect






[CLJS-1867] Analyzer error when running a project with compiler build from master Created: 10/Dec/16  Updated: 11/Dec/16  Resolved: 11/Dec/16

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

Type: Defect Priority: Minor
Reporter: Roman Liutikov Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None


 Description   

I was about to test a new externs inference on a sample project and got the following analyzer error:

----  Could not Analyze  resources/public/js/compiled/out/sablono/interpreter.cljc   line:84  column:12  ----

   at line 84 resources/public/js/compiled/out/sablono/interpreter.cljc

  82  (when (some? props)
  83    (when (nil? (.-value props))
  84      (set! (.-value props) js/undefined))
          ^---  at line 84 resources/public/js/compiled/out/sablono/interpreter.cljc
  85    (when (nil? (.-checked props))
  86      (set! (.-checked props) js/undefined)))
  87  (if (empty? children)

ClojureScript build is done from commit 97aa4303f46.

Project dependencies are:

[[org.clojure/clojure "1.8.0"]
 [org.clojure/clojurescript "1.9.363"]
 [rum "0.10.7"]]

The code:

(ns app.core
  (:require [rum.core :as rum]))

Note that this compiles without errors with the latest ClojureScript release 1.9.293



 Comments   
Comment by David Nolen [ 11/Dec/16 9:08 AM ]

There's currently very little useful information in this issue. Do not report error information not directly produced by the ClojureScript compiler. This issue will be closed shortly if it's not corrected. Thanks.

Comment by David Nolen [ 11/Dec/16 9:24 AM ]

I've probably fixed the issue in master. But in the future, issues must be more informative and more minimal.





[CLJS-1806] build api fails to generate inline code for :target :nodejs Created: 01/Oct/16  Updated: 09/Dec/16

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

Type: Defect Priority: Minor
Reporter: Bruce Hauman Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None


 Description   

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.

;; this outputs code
(cljs.build.api/build (cljs.build.api/inputs '[(ns hello.core) (+ 1 2)]) {}) 

;; this 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)] {}) ;; this outputs code

(cljs.build.api/build '[(ns hello.core) (+ 1 2)] {:target :nodejs}) ;; this outputs code


 Comments   
Comment by Bruce Hauman [ 30/Oct/16 11:31 AM ]

From @ykomatsu on Github:

add-preloads seems to remove cljs/nodejs.cljs.

https://github.com/clojure/clojurescript/blob/ab7a4911f1fd3a81210b1a9f2d84857748f8268b/src/main/clojure/cljs/closure.clj#L897

This patch will fix this problem but I am not sure if this is correct solution.

https://github.com/ykomatsu/clojurescript/commit/fc986467e66e6a628dc8f0e8a2ef2b30f715fd23

Comment by Dusan Maliarik [ 09/Dec/16 2:15 PM ]

Would anyone from the team please look at the patch? Thank you

Comment by David Nolen [ 09/Dec/16 6:22 PM ]

Please attach a patch to the ticket for review. Linking out of JIRA is not desirable. Thanks.





[CLJS-1865] Google Closure Compiler in JavaScript Created: 06/Dec/16  Updated: 06/Dec/16

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

Type: Enhancement Priority: Trivial
Reporter: James Thornton Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Google released its JavaScript version of the Closure Compiler – "this allows Closure Compiler to run entirely in JS. Java is not required":

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.

NB: I discovered this while experimenting with using ClojureScript with Polymer:






[CLJS-1718] Foreign lib files should be placed in a location that matches their namespace Created: 29/Jul/16  Updated: 02/Dec/16  Resolved: 02/Dec/16

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

Type: Defect Priority: Critical
Reporter: António Nuno Monteiro Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None
Environment:

Affects master



 Description   

Using several foreign libs with the same file name ends up just including one of them, as the files are placed at the root of the `:output-dir`.

A solution for this would be placing those files in a location that matches their `:provides` namespace.



 Comments   
Comment by David Nolen [ 02/Dec/16 5:11 PM ]

fixed https://github.com/clojure/clojurescript/commit/97d2d61e78ce747d02d0e5b2ced706f6fb68ec4e





[CLJS-1864] timestamped source maps broken with Node Created: 29/Nov/16  Updated: 30/Nov/16

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

Type: Defect Priority: Minor
Reporter: Dmitr Sotnikov Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

I'm using Figwheel with Node, and noticed a bug with timestamped source maps. When the :source-map-timestamp compiler flag is set, the sourceMappingURL is set to source.js.map?timestamp.

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 :target is :node and output something like source.js.timestamp.map instead, and use it directly as the value of sourceMappingURL.

Here's a change I made locally in cljs.compiler/emit-source-map that allows source maps to be resolved on Node when using timestamps:

emit-source-map
(defn emit-source-map [src dest sm-data opts]
     (let [timestamp (System/currentTimeMillis)
           filename (str (.getPath ^File dest)
                         (when (and
                                 (true? (:source-map-timestamp opts))
                                 (= (:target opts) :nodejs))
                           (str "." timestamp))
                         ".map")
           sm-file  (io/file filename)]
       (if-let [smap (:source-map-asset-path opts)]
         (emits "\n//# sourceMappingURL=" smap
                (string/replace (util/path sm-file)
                                (str (util/path (io/file (:output-dir opts))))
                                "")
                (if (and (true? (:source-map-timestamp opts))
                         (not= (:target opts) :nodejs))
                  (str
                    (if-not (string/index-of smap "?") "?" "&")
                    "rel=" timestamp)
                  ""))
         (emits "\n//# sourceMappingURL="
                (or (:source-map-url opts) (.getName sm-file))
                (if (and (true? (:source-map-timestamp opts))
                         (not= (:target opts) :nodejs))
                  (str "?rel=" 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->relpath (first (:provides opts)) (:ext opts))}}))))


 Comments   
Comment by David Nolen [ 30/Nov/16 8:32 AM ]

Does Node.js have source map caching issues? The timestamp feature was created for caching issues present in web browsers.

Comment by Dmitr Sotnikov [ 30/Nov/16 8:39 AM ]

I tried it with :source-map-timestamp set to false, and source maps got out of sync when Cljs sources were reloaded.

Comment by David Nolen [ 30/Nov/16 10:01 AM ]

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.

Comment by Dmitr Sotnikov [ 30/Nov/16 2:56 PM ]

Sounds like a plan.

Comment by David Nolen [ 30/Nov/16 7:25 PM ]

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.

Comment by Dmitr Sotnikov [ 30/Nov/16 7:28 PM ]

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.





[CLJS-1863] :reload/:reload-all issue with .cljc runtime/macro nses Created: 29/Nov/16  Updated: 29/Nov/16

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

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


 Description   

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)`.



 Comments   
Comment by David Nolen [ 29/Nov/16 3:59 PM ]

Whatever we do needs to be copied over into a bootstrapped, but that's a separate issue.





[CLJS-1862] allow NodeJS's NODE_MODULES to be set as a REPL option Created: 28/Nov/16  Updated: 29/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Marc Daya Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: nodejs, repl

Attachments: Text File 65.patch    
Patch: Code

 Description   

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.



 Comments   
Comment by David Nolen [ 28/Nov/16 4:26 PM ]

Thanks. Have you submitted your Clojure CA yet?

Comment by Marc Daya [ 29/Nov/16 2:02 PM ]

It has just been filed.





[CLJS-1860] Resolve JS modules referred by their fully-qualified namespace Created: 24/Nov/16  Updated: 28/Nov/16  Resolved: 28/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Major
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1860.patch    
Patch: Code

 Description   

This is part 2 of CLJS-1848. When a JS module is used in a macro, the analyzer should find the correct `full-ns` if the module is fully qualified.

Without this patch, downstream namespaces that use the macro would need to explicitly require the JS module. This shouldn't be necessary if the module has already been required in the namespace that declares the macro.

This patch doesn't introduce any new behavior. Instead, it mimics the current CLJS namespaces behavior for JS modules.



 Comments   
Comment by David Nolen [ 28/Nov/16 8:46 AM ]

fixed https://github.com/clojure/clojurescript/commit/79a20afe360249ab6cb652f4465b7ccd01a923f2





[CLJS-1861] Use usr/bin/env in build scripts for portability Created: 25/Nov/16  Updated: 28/Nov/16  Resolved: 28/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1861.patch    

 Description   

There are a couple of build scripts where

#!/bin/bash
could be converted to
#!/usr/bin/env bash
for additional portability.



 Comments   
Comment by David Nolen [ 28/Nov/16 8:40 AM ]

fixed https://github.com/clojure/clojurescript/commit/170fd767752a4839b25038c86b2d6a6aa3b25ab7





[CLJS-1858] Should allow `:cache-analysis true` and `cache-analysis-format nil` Created: 21/Nov/16  Updated: 22/Nov/16  Resolved: 22/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Major
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1858.patch    
Patch: Code

 Description   

This was intended but doesn't actually work.



 Comments   
Comment by David Nolen [ 22/Nov/16 1:00 PM ]

fixed https://github.com/clojure/clojurescript/commits/master





[CLJS-1857] Fix self-host tests Created: 20/Nov/16  Updated: 21/Nov/16  Resolved: 21/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Major
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1857.patch    
Patch: Code

 Description   

self-hosted tests are broken in master given the latest externs inference commits.



 Comments   
Comment by Mike Fikes [ 20/Nov/16 1:23 PM ]

+1 LGTM and script/test-self-parity, script/test-self-host, and script/test all pass for me (apart from the expected Nashorn error we have been seeing recently)

Comment by David Nolen [ 21/Nov/16 3:00 PM ]

fixed https://github.com/clojure/clojurescript/commit/e156e74fcd1dfa70fb0f35d187825dd9b131431c





[CLJS-1856] Self-host: load-deps doesn't delegate to itself Created: 17/Nov/16  Updated: 18/Nov/16  Resolved: 18/Nov/16

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

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: bootstrap

Attachments: Text File CLJS-1856.patch    
Patch: Code

 Description   

The first arity of cljs.js/load-deps should be calling the second arity of itself, but it is currently inadvertently making a call to cljs.js/analyze-deps.

Note: This arity is not being used. The arguments being passed along were properly updated with CLJS-1826, but it is now actually inadvertently calling analyze-deps with an arity error. (The real fix is to make it call load-deps).



 Comments   
Comment by Alex Miller [ 18/Nov/16 7:54 PM ]

dnolen comment lost in system migration:

fixed https://github.com/clojure/clojurescript/commit/e01b8a0366f5c0519a6fa49025592bb345718235





[CLJS-1855] Subvec should implement IIterable Created: 17/Nov/16  Updated: 18/Nov/16  Resolved: 18/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Thomas Mulvaney Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1855.patch    
Patch: Code

 Description   

Currently calling `iter` on a `Subvec` falls back to `seq-iter`. We can obtain performance equal to `PersistentVector` iteration by using `ranged-iterator`. This also brings Subvecs more inline with the Clojure implementation.

Benchmark:

(simple-benchmark [sv (subvec (into [] (range 1000000)) 0 1000000)]
                  (let [i (iter sv)]
                    (loop []
                      (if (.hasNext i)
                        (do (.next i)
                            (recur)))))
                  100)
Engine Master (ms) Patch (ms) Gain (master/patch)
V8 41979 3550 11x
jsc 29348 2405 12x

`ChunkedSeqs` could gain the same performance boost by implementing IIterable and utilizing `ranged-iterator` however this would deviate from Clojure implementation wise.



 Comments   
Comment by Alex Miller [ 18/Nov/16 7:54 PM ]

dnolen comment lost in system migration:

fixed https://github.com/clojure/clojurescript/commit/d2cb3eeca6f37ef36e28be9975db3816d04355a1





[CLJS-1643] Emit more informative error when emitting a type which has no emit multimethod case Created: 21/May/16  Updated: 18/Nov/16  Resolved: 18/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

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

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

 Description   

Users may accidentally splice in Clojure functions and other things in macros that work in Clojure which cannot work in ClojureScript. We may want to include a default warning for the most common/likely error cases.



 Comments   
Comment by António Nuno Monteiro [ 13/Nov/16 8:27 AM ]

Attached patch with fix and test.

Comment by Alex Miller [ 18/Nov/16 7:52 PM ]

dnolen comment lost in system migration:

fixed https://github.com/clojure/clojurescript/commit/417350ddabea283ef8f576b8e361a249d9bfb9e7





[CLJS-1816] Basic timing info in verbose output Created: 11/Oct/16  Updated: 18/Nov/16  Resolved: 18/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Enhancement Priority: Minor
Reporter: Martin Klepsch Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: compiler, newbie

Attachments: Text File CLJS-1816.patch    
Patch: Code

 Description   

When logging verbose output during compilation of individual namespaces we could include basic timing information to make it easier to spot slow-to-compile namespaces.



 Comments   
Comment by António Nuno Monteiro [ 13/Nov/16 6:42 AM ]

Attached patch with fix.

Comment by Alex Miller [ 18/Nov/16 7:53 PM ]

dnolen comment lost in system migration:

fixed https://github.com/clojure/clojurescript/commit/6602f769ed4d52fd67577aacaf9cfe6db05b8ef3





[CLJS-1616] Self-host: improve documentation for compile-str Created: 06/Apr/16  Updated: 18/Nov/16  Resolved: 18/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Yehonathan Sharvit Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: docstring

Attachments: Text File CLJS-1616.patch    
Patch: Code

 Description   

It's not clear at all how to use the `opts` arguments for compile-str.

In the code - https://github.com/clojure/clojurescript/blob/c3899acf797eb6779c53b313f5606c5018360b83/src/main/cljs/cljs/js.cljs#L660 - we
only have
:load - library resolution function, see load-fn
:source-map - set to true to generate inline source map information

In fact, there is also :verbose and ::def-emits-var

They are not documented.

Are there more options?



 Comments   
Comment by António Nuno Monteiro [ 13/Nov/16 8:53 AM ]

Attached patch with fix.

Comment by Alex Miller [ 18/Nov/16 7:52 PM ]

dnolen comment lost in system migration:

fixed https://github.com/clojure/clojurescript/commit/33a7e5bcac763d40ca684404cf772e9745d264a





[CLJS-901] Protocolize compiler access to the file system Created: 03/Dec/14  Updated: 18/Nov/16

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

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


 Description   

Currently builds are based on files on disk. It is desirable to be able to instead get in memory builds, WebDAV based builds, S3 based builds, etc. Many of these alternative strategies are not in scope for the ClojureScript compiler but this does not mean we should not supply the needed hooks for users to control the behavior.



 Comments   
Comment by Thomas Heller [ 03/Dec/14 9:31 AM ]

This and some other issues opened recently (CLJS-900, CLJS-851, CLJS-899, ...) have some overlap with what I have done in shadow-build [1]. Memory based builds are actually already possible cause it will only touch the disk when asked to, although the API could use some cleanup.

Anyways, might be worthwhile to coordinate these efforts to make CLJS more accessible for everyone.

[1] https://github.com/thheller/shadow-build

Comment by Alan Dipert [ 04/Feb/15 11:36 AM ]

I too think it would be totally awesome to have builds based on sources from disparate places.

One alternative in this spirit I have been thinking about is a "SourceSet" approach. The idea is, instead of teaching CLJS how to consume various place-types directly via protocols, provide an API for building a "SourceSet" value and also a build function that takes the SourceSet as input. I imagine the SourceSet in its simplest form as a map of namespaces to string sources.

With a value to represent sources that is place-agnostic and immutable, 3rd party tools can consume/emit/transform these values before invoking a compile without knowledge or interest in CLJS internals. Conversely CLJS need not be concerned with how SourceSets are constructed.

This whole idea is inspired by boot's FileSets, which work basically the same but can't have the "it fits in memory" assumption.





[CLJS-1854] Self-host: Reload ns with const Created: 16/Nov/16  Updated: 16/Nov/16

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

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


 Description   

Bootstrapped ClojureScript fails to allow you to reload a namespace containing a constant.

To reproduce, evaluate the following forms in a REPL:

(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 "(ns foo.core) (def ^:const x 1)"}))}
  prn)

(cljs.js/eval st
  '(require (quote foo.core) :reload)
  {:context :expr
   :eval cljs.js/js-eval
   :load (fn [_ cb]
           (cb {:lang :clj
                :source "(ns foo.core) (def ^:const x 2)"}))}
  prn)

The expectation is that the :reload directive in the last require will allow the namespace to be loaded with the const def being re-defined.

Instead, you get the following in the eval callback:

{:error #error {:message "Could not eval foo.core", :data {:tag :cljs/analysis-error}, :cause #error {:message "Can't redefine a constant at line 1 ", :data {:file nil, :line 1, :column 15, :tag :cljs/analysis-error}}}}

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 require capability (CLJS-1346).

FWIW, Planck has been working around this (and violating public API), manipulating cljs.js/*loaded* via its require REPL special, essentially purging portions of the analysis cache when reloading: https://github.com/mfikes/planck/blob/1.17/planck-cljs/src/planck/repl.cljs#L329-L348






[CLJS-1758] QuickStart guide fails at browser REPL step with "TypeError: parentElm is null" Created: 18/Aug/16  Updated: 16/Nov/16  Resolved: 18/Aug/16

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

Type: Defect Priority: Minor
Reporter: Tim McCormack Assignee: Unassigned
Resolution: Not Reproducible Votes: 0
Labels: None


 Description   

When I follow http://clojurescript.org/guides/quick-start up to the browser REPL step, I get an error in the browser console and the REPL never connects. The browser error is TypeError: parentElm is null on line 482 of crosspagechannel.js: parentElm.appendChild(iframeElm);.

I have put up a self-contained example to demonstrate the bug: https://github.com/timmc/sscce-CLJS-1758

  • I am using this command to run the REPL: rlwrap java -cp cljs-1.9.216.jar:src clojure.main repl.clj
  • Refreshing the browser does not help.
  • Using Chromium 52.0.2743.116 instead of Firefox ESR 45.3.0 does not help.
$ java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

$ uname -a
Linux bc-timmc 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux
(Debian GNU/Linux 8.5)


 Comments   
Comment by Tim McCormack [ 18/Aug/16 11:27 AM ]

CLJS 1.9.89 fails the same way.

Comment by António Nuno Monteiro [ 18/Aug/16 11:51 AM ]

Not a bug. Your index.html file needs to at least have a `<body>` tag.
All html examples in the quickstart provide valid HTML, you just chose not to use it.

Comment by Tim McCormack [ 18/Aug/16 12:41 PM ]

Ah, of course! I compared the other files with the demo, but not that one!

I could have sworn the body element was always created automatically in the DOM whether or not it was declared. TIL.

(And confirmed, it works now.)

ETA: Not sure which resolution to pick, so leaving open.

Comment by HU Ze [ 16/Nov/16 4:17 AM ]

I am facing same problem before, I think you put your <script> in <head> and actually it MUST be put in <body>. To make it simply, just copy and paste from the Quick Start.





[CLJS-1852] explain-data problems don't provide resolved symbols under :pred Created: 15/Nov/16  Updated: 15/Nov/16

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

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


 Description   

Same as http://dev.clojure.org/jira/browse/CLJ-2059 which has a patch.






[CLJS-1846] Range issues Created: 10/Nov/16  Updated: 15/Nov/16

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

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

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

 Description   

Problem
There are a number of bugs with Range which occur when the step size is 0 or where negative.

Examples

cljs.user=> (count (range 10 0 0))
-Infinity  ;Expect Infinity

cljs.user=> (nth (range 10 0 -1) -1)
11 ; Expected IndexOutOfBounds

cljs.user=> (take 5 (sequence identity (range 0 10 0)))
() ; Expected (0 0 0 0 0)

cljs.user=> (into [] (take 5) (range 0 10 0))
[] ; Expected [0 0 0 0 0]


 Comments   
Comment by David Nolen [ 10/Nov/16 4:37 PM ]

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!

Comment by Thomas Mulvaney [ 15/Nov/16 8:24 AM ]

Updated patch with performance tweaks.

  • Added the ^boolean annotation to the `some-range?` helper.
  • Removed calls to methods of Range where possible.
  • Improved 2-arity reduces performance over master significantly by replacing the call to ci-reduce.




[CLJS-1651] Self-host: Cannot replace core macro-function Created: 28/May/16  Updated: 14/Nov/16  Resolved: 14/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: bootstrap

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

 Description   

Replace double to multiply by two in self host and you will see that operator-position resolution chooses the core macro:

ClojureScript Node.js REPL server listening on 54425
To quit, type: :cljs/quit
cljs.user=> (require 'cljs.js)
nil
cljs.user=> (def st (cljs.js/empty-state))
#'cljs.user/st
cljs.user=> (cljs.js/eval-str st "(defn double [x] (* 2 x))" nil {:eval cljs.js/js-eval :context :expr} identity)
WARNING: double already refers to: cljs.core/double being replaced by: cljs.user/double at line 1
{:ns cljs.user, :value #object[cljs$user$double "function cljs$user$double(x){
return ((2) * x);
}"]}
cljs.user=> (cljs.js/eval-str st "[(double 3) (apply double [3])]" nil {:eval cljs.js/js-eval :context :expr} identity)
{:ns cljs.user, :value [3 6]}

The correct result above would be [6 6].



 Comments   
Comment by António Nuno Monteiro [ 13/Nov/16 11:27 AM ]

Attached patch with fix and test.

Comment by Mike Fikes [ 13/Nov/16 12:07 PM ]

Confirmed that António's patch fixes things downstream in Planck.

Comment by David Nolen [ 14/Nov/16 1:43 PM ]

fixed https://github.com/clojure/clojurescript/commit/4abcec8b7af601cb21342a559f5ee731fb19f7ff





[CLJS-1764] Double warning for undeclared Var Created: 26/Aug/16  Updated: 14/Nov/16

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

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

Attachments: Text File CLJS-1764.patch    
Patch: Code

 Description   

A regression occurred where an undeclared Var in a {{require}}d file causes two diagnostics:

$ more src/foo/core.cljs
(ns foo.core)

(def x 2)

abc
$ rm -rf .cljs_node_repl
$ java -cp cljs-1.9.227.jar:src clojure.main -m cljs.repl.node
ClojureScript Node.js REPL server listening on 52749
To quit, type: :cljs/quit
cljs.user=> *clojurescript-version*
"1.9.227"
cljs.user=> (require 'foo.core)
WARNING: Use of undeclared Var foo.core/abc at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Use of undeclared Var foo.core/abc at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
nil
cljs.user=> :cljs/quit
$ rm -rf .cljs_node_repl
$ java -cp cljs-1.9.211.jar:src clojure.main -m cljs.repl.node
ClojureScript Node.js REPL server listening on 56704
To quit, type: :cljs/quit
cljs.user=>  *clojurescript-version*
"1.9.211"
cljs.user=> (require 'foo.core)
WARNING: Use of undeclared Var foo.core/abc at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
nil
cljs.user=> :cljs/quit


 Comments   
Comment by David Nolen [ 16/Sep/16 2:04 PM ]

If somebody wants to do a git bisect to sort this one out, that would be awesome

Comment by António Nuno Monteiro [ 07/Nov/16 9:34 AM ]

Only seems to happen at the REPL

Comment by António Nuno Monteiro [ 13/Nov/16 3:47 PM ]

Patch with fix.

This only happened when `require`ing at the REPL. Required namespaces ended up being analyzed twice, once in `cljs.repl` and once in `cljs.closure`. The patch adds wraps compiling these NSes in `cljs.closure` in a `cljs.analyzer/no-warn`.

Comment by David Nolen [ 14/Nov/16 9:24 AM ]

How will this not effect non REPL cases?

Comment by António Nuno Monteiro [ 14/Nov/16 9:29 AM ]

I just now realized that it will probably affect those cases as well, although the `add-dependencies` function seems to (currently) only be used in `cljs.repl`. What other approach should I try? Restrict the cases where we

*analyze-deps*
at the REPL?

Comment by Thomas Heller [ 14/Nov/16 9:51 AM ]

FWIW I don't think this is related to the REPL at all.

I have been seeing doubled warnings for a while now in shadow-build but never bothered to find you why.

abc

(defn x [y] xyz)

Will always warn twice about "xzy" but only once for "abc", doesn't matter if a REPL is involved or not.





[CLJS-1848] Analyzer can't find JS modules during macro-expansion Created: 12/Nov/16  Updated: 13/Nov/16  Resolved: 13/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Major
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1848-1.patch     Text File CLJS-1848-2.patch     Text File CLJS-1848.patch    
Patch: Code and Test

 Comments   
Comment by António Nuno Monteiro [ 12/Nov/16 4:23 AM ]

Attached patch with fix.

Comment by David Nolen [ 12/Nov/16 11:43 AM ]

Is there some example demonstrating that this needs to be fixed?

Comment by António Nuno Monteiro [ 12/Nov/16 1:23 PM ]

Turned out the problem was related to finding processed JS modules during macro-expansion.

Changed the patch to add a mapping from the module provide to itself, such that macro-expansion can see that a module for that name exists.

Updated the module processing tests accordingly.

Comment by António Nuno Monteiro [ 12/Nov/16 6:04 PM ]

Actually disregard patch CLJS-1848-1.patch, as I've come to realize there's a much cleaner way to solve this issue. I'll provide a new patch shortly.

Comment by António Nuno Monteiro [ 13/Nov/16 4:06 AM ]

Patch CLJS-1848-2.patch contains the appropriate fix and explanation.

Comment by David Nolen [ 13/Nov/16 10:23 AM ]

fixed https://github.com/clojure/clojurescript/commit/1288204b043e00ca39b0c3c5af7fc8ac7eece816





[CLJS-1194] data_readers.cljc Created: 10/Apr/15  Updated: 12/Nov/16  Resolved: 12/Nov/16

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

Type: Enhancement Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Completed Votes: 2
Labels: None

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

 Description   

Now that conditional reading has landed we can implement support for data_readers.cljc to get both compile time and runtime support.



 Comments   
Comment by David Nolen [ 10/Apr/15 7:45 PM ]

This needs http://dev.clojure.org/jira/browse/CLJ-1699 to be useful.

Comment by Nikita Prokopov [ 19/May/15 7:58 AM ]

CLJ-1699 has landed.

Right now CLJS tries to compile data_readers.cljc as a regular source code file:

Exception in thread "main" java.lang.AssertionError: No ns form found in src/data_readers.cljc, compiling:(/private/var/folders/0h/9vv4g3d955l6ctwwl4k9xjy40000gn/T/form-init3533791126017861878.clj:1:125)
	at clojure.lang.Compiler.load(Compiler.java:7249)
	at clojure.lang.Compiler.loadFile(Compiler.java:7175)
	at clojure.main$load_script.invoke(main.clj:275)
	at clojure.main$init_opt.invoke(main.clj:280)
	at clojure.main$initialize.invoke(main.clj:308)
	at clojure.main$null_opt.invoke(main.clj:343)
	at clojure.main$main.doInvoke(main.clj:421)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
Comment by David Nolen [ 19/May/15 8:53 AM ]

This should be addressed first: http://dev.clojure.org/jira/browse/CLJS-1277

Comment by António Nuno Monteiro [ 12/Nov/16 11:06 AM ]

Attached patch with fix and tests.

Comment by David Nolen [ 12/Nov/16 11:55 AM ]

fixed https://github.com/clojure/clojurescript/commit/9484a134bdf039c10ec3c26c8aaa3acd0dcd9875





[CLJS-1851] Only output JS module processing time when `:compiler-stats` is true Created: 12/Nov/16  Updated: 12/Nov/16  Resolved: 12/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Minor
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1851.patch    
Patch: Code

 Comments   
Comment by António Nuno Monteiro [ 12/Nov/16 6:36 AM ]

Attached patch with fix.

Comment by David Nolen [ 12/Nov/16 11:49 AM ]

fixed https://github.com/clojure/clojurescript/commit/f108ce85e9364e041b932af8071ba918b2380b02





[CLJS-1850] *unchecked-if* not declared ^:dynamic warning after commit a732f0 Created: 12/Nov/16  Updated: 12/Nov/16  Resolved: 12/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Minor
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1850.patch    
Patch: Code

 Description   

The following commit introduced a warning when requiring the analyzer in the `:cljs` branch:
https://github.com/clojure/clojurescript/commit/a732f07456c997b113a7c020e627cfe614ec31fc



 Comments   
Comment by António Nuno Monteiro [ 12/Nov/16 5:21 AM ]

Attached patch with fix.

Comment by David Nolen [ 12/Nov/16 11:48 AM ]

fixed https://github.com/clojure/clojurescript/commit/617ce7d4e33f65352be3d6d4865ace2996d65bcc





[CLJS-1849] Self-host: regression introduced by CLJS-1794 Created: 12/Nov/16  Updated: 12/Nov/16  Resolved: 12/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Major
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1849.patch    
Patch: Code

 Description   

Self-hosted tests are erroring due to the fix introduced in CLJS-1794.



 Comments   
Comment by António Nuno Monteiro [ 12/Nov/16 5:15 AM ]

Attached patch with fix.

Comment by David Nolen [ 12/Nov/16 11:47 AM ]

fixed https://github.com/clojure/clojurescript/commit/cebfb586355b526253fdd25965de976b49a6973e





[CLJS-1186] add :postamble option to compiler Created: 02/Apr/15  Updated: 11/Nov/16  Resolved: 10/Aug/16

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

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

Attachments: Text File cljs_1186.patch    

 Description   

Similar to CLJS-723:

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



 Comments   
Comment by David Nolen [ 12/Feb/16 4:42 PM ]

Would like to hear more use cases for this one.

Comment by David Nolen [ 10/Aug/16 2:42 PM ]

Not going to do this one.

Comment by Tom Connors [ 11/Nov/16 4:28 PM ]

I've got a use case for this, if you're willing to reconsider. I'd like to set window.React and window.ReactDOM back to whatever they were before the script executed, like jQuery.noConflict and similar. So my preamble file would contain:
(function(){ var oldReact = window.React; and my postamble would contain: window.React = oldReact; }());





[CLJS-1844] Copy over GSoC externs parsing code Created: 08/Nov/16  Updated: 11/Nov/16  Resolved: 11/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.293
Fix Version/s: Next

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


 Description   

We should copy over Maria Geller's externs parsing work https://github.com/mneise/clojurescript/commits/CLJS-1074



 Comments   
Comment by David Nolen [ 11/Nov/16 12:52 PM ]

fixed https://github.com/clojure/clojurescript/commit/498c1da144eee7011cf57a392274e9166ff146b7





[CLJS-1822] Use `:file-min` when processing JS modules with advanced optimizations Created: 15/Oct/16  Updated: 11/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

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

 Description   

Currently the `:file-min` option is ignored if a foreign lib is a JS module. Certain libraries produce 2 different artifacts, one which has development time checks, and a production-ready bundle which doesn't.

This patch proposes that `:file-min` in a JS module be fed to the Google Closure Compiler (instead of `:file`) when processing JS modules in `simple` or `advanced` compilation. This way, the development bundle of a JS module can be used with `:optimizations :none`, while the production-ready bundle can be used when compiling projects for production use.



 Comments   
Comment by António Nuno Monteiro [ 05/Nov/16 12:05 PM ]

Attached patch with fix and test.





[CLJS-1845] assoc on Subvec doesn't check bounds. Created: 09/Nov/16  Updated: 11/Nov/16  Resolved: 11/Nov/16

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

Type: Defect Priority: Minor
Reporter: Thomas Mulvaney Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

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

 Description   

It is possible to call assoc on a Subvec at index n where n is anywhere in the bounds of the backing vector.

Example

cljs.user=> (assoc (subvec [0 1 2 3 4 5 6 7 8] 0 3) 8 0)
[0 1 2 3 4 5 6 7 0]

Expected behaviour

Throw an error: Index 8 out of bounds [0,3]



 Comments   
Comment by David Nolen [ 11/Nov/16 12:27 PM ]

fixed https://github.com/clojure/clojurescript/commit/e28e3f2ce78d6781c549f6e757194600d8db4cfc





[CLJS-1847] REPL should recognize `clojure.core/load` Created: 11/Nov/16  Updated: 11/Nov/16  Resolved: 11/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Minor
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: repl

Attachments: Text File CLJS-1847.patch    
Patch: Code

 Comments   
Comment by António Nuno Monteiro [ 11/Nov/16 10:39 AM ]

Attached patch with fix.

Comment by David Nolen [ 11/Nov/16 12:23 PM ]

fixed https://github.com/clojure/clojurescript/commit/140eb7a7b6213f7dfb5cc01ea5e95c267d510a8b





[CLJS-349] cljs.compiler: No defmethod for emit-constant clojure.lang.LazySeq Created: 30/Jul/12  Updated: 08/Nov/16

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

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

Attachments: Text File 0001-CLJS-349-Allow-ISeq-to-be-emitted-by-macros-as-a-con.patch     File fixbug349.diff    

 Description   

The cljs compiler errors when trying to emit-constant for a clojure.lang.LazySeq.

Example : https://www.refheap.com/paste/3901

Here syms is defined as a LazySeq on line 3, then on line 7 it is quoted. The error is included in the refheap.

Emitting a cljs.core.list for this type seems to solve the issue.



 Comments   
Comment by David Nolen [ 31/Aug/12 9:27 AM ]

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!

Comment by Herwig Hochleitner [ 28/Oct/12 9:31 PM ]

The lazy seq seems to be introduced on line 7, the '~syms form

`(let [mappings# (into {} (map-indexed #(identity [%2 %1]) '~syms))

Clojure allows lazy-seqs to be embedded: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L4538

As an aside: The relevant protocol is not literality, but the print-dup multimethod. Do / Should we have print-dup in CLJS?

Comment by Herwig Hochleitner [ 31/Oct/12 10:10 PM ]

Attached patch 0001 doesn't add a case for LazySeq, but folds two cases for PersistentList and Cons into one for ISeq.

Comment by David Nolen [ 19/Nov/13 9:28 PM ]

This approach seems acceptable but this is an old patch can we update for master?





[CLJS-712] resolve-var for symbol with dot still wrong Created: 03/Dec/13  Updated: 08/Nov/16

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

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


 Description   

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.






[CLJS-719] this-as behaves incorrectly in "scoping function" Created: 07/Dec/13  Updated: 08/Nov/16

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

Type: Defect Priority: Major
Reporter: Kevin Marolt Assignee: David Nolen
Resolution: Unresolved Votes: 1
Labels: None


 Description   

When a this-as expression gets put in a "scoping function", e.g. in a let-binding, the value bound via this-as refers to the scoping function, and not to the outer scope.

Example:

(def foo
  (js-obj
    "bar" "baz"
    "getBarRight" (fn [] (this-as self (.-bar self)))
    "getBarWrong" (fn []
                    (let [bar (this-as self (.-bar self))]
                      bar))))
     
(.log js/console (.getBarRight foo)) ;; => "baz"
(.log js/console (.getBarWrong foo)) ;; => undefined

Whereas foo.getBarRight expands to something like

function() {
  var self = this; // this refers to foo
  return self.bar; // returns "bar"
}

foo.getBarWrong on the other hand expands to

function() {
  var bar = function() {
    var self = this; // this refers to enclosing function
    return self.bar; // returns undefined
  }();
  return bar; // returns undefined
}





[CLJS-868] no arity warnings on recursive calls Created: 03/Oct/14  Updated: 08/Nov/16

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

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

Attachments: File cljs_868_14_Nov_2015.md     Text File cljs_868_14_Nov_2015.patch    

 Description   

If a function recursively invokes itself within its own body the invoke will not be checked for arity mismatch.



 Comments   
Comment by Samuel Miller [ 10/Aug/15 10:06 PM ]

Took some time to look at this issue. Originally thought "Do what loop/recur does" but that does not take into account multi-arity. It seems like maybe the best option is to somehow use the second pass of the analyze(analyze-fn-methods-pass2). The entire information about the function is present and the warning section of the code gets triggered but because of no-warn is ignored. Any other ideas for a solution to this?

Comment by Samuel Miller [ 14/Nov/15 7:47 PM ]

So I am looking for feed back on this patch and I will try to explain the reasoning for each section.

The issue is that a function only knows about it's arity after it has been parsed once.
So we need to check arity issues on the second pass

First off, added two new variables.
-activate-second-pass-warnings:Boolean Basically if you want to have second-pass warnings turned on
-second-pass-cljs-warnings:Set Right now we only have :fn-arity but I figure might as well make it generic.

So first up if the modifications to the analyze-fn-methods-pass2 function.
Instead of using no-warn marco here we have some new functionality.
The goal is to turn everything off except the second-pass warnings

So if activate-second-pass-warnings is false just use no-warn else it will use the new section of code.

The default-warning-handler was also modified. After checking if a warning is on, it checks if the warning is a second-pass warning and
if that warning can now be activated. If activate-second-pass-warnings is false AND a warning is still on that implies it is a second pass warning
in the second pass so we activate it.

Also I tried to keep all modifications in cljs.analyzer.

Originally I had the cljs-warnings :fn-arity to false and it would only be turned on in the second pass.
However the repl section just sets everything to true (and turns off select parts like ns errors).
So I decided to not touch those sections and instead keep how other files interface with the analyzer the same.

Comment by Samuel Miller [ 16/Nov/15 10:58 PM ]

Just realized that I have the patch marked as .md instead of .patch





[CLJS-968] Metadata on function literal inside of a let produces invalid Javascript Created: 07/Jan/15  Updated: 08/Nov/16

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

Type: Defect Priority: Major
Reporter: Bobby Eickhoff Assignee: David Nolen
Resolution: Unresolved Votes: 2
Labels: bug
Environment:

Originally found with [org.clojure/clojurescript "0.0-2496"]
Still reproducible with the latest cljsc (b5e9a5116259fc9f201bee4b9c6564f35306f9a5)



 Description   

Here is a minimal test case that produces the invalid Javascript:

(defn f []
  (let [a 0]
    ^{"meta" "data"}
    (fn [] true)))

The compiled Javascript includes the invalid token sequence "return return". (Per Chrome: Uncaught SyntaxError: Unexpected token return)

The problem does not occur if the metadata applies to a map literal instead of a function literal.
The problem only occurs when the function and metadata are inside of a let.



 Comments   
Comment by Bobby Eickhoff [ 07/Jan/15 9:45 PM ]

I forgot to try with-meta. Using with-meta does not produce this syntax error, so it's only a problem with the reader macro for metadata.

Comment by David Nolen [ 08/Jan/15 7:41 AM ]

Any quick thoughts about this one Nicola? Quite possibly a compiler issue on the CLJS side.

Comment by Nicola Mometto [ 08/Jan/15 8:07 AM ]

David, I understand why this happens but I don't know enough about how cljs's js emission to propose a fix.
The issue is that with this commit: https://github.com/clojure/clojurescript/commit/d54defd32d6c5ffcf6b0698072184fe8ccecc93a the following scenario is possible:

{:op :meta
 :env {:context :return}
 :expr {:op :fn
        :env {:context :expr}
        :methods [{:op :fn-method 
                   :env {:context :return} ..}]
        ..}
 ..}

i.e. analyze-wrap-meta changes the context of the :fn node to :expr but keeps the context of the :fn-methods to :return.

This causes both
https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/compiler.clj#L575-L576
and
https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/compiler.clj#L488 (https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/compiler.clj#L233)

to be true and emit a "return".

Comment by David Nolen [ 06/May/15 7:15 PM ]

Hrm, it appears analyze-wrap-meta may need to defer to a helper to change the :context of the given AST node.

Comment by Herwig Hochleitner [ 11/Dec/15 10:52 AM ]

I just randomly ran into this, when upgrading an old project. There is also a duplicate already: http://dev.clojure.org/jira/browse/CLJS-1482

Comment by Jonathan Chu [ 28/Jan/16 6:19 PM ]

This issue occurs for me even without a let.

(fn []
  ^{"meta" "data"}
  (fn [] true))

gives me

#object[SyntaxError SyntaxError: Unexpected token return]




[CLJS-375] loop doesn't seem to preserve tag information as evidenced by extra cljs.core.truth_ calls Created: 06/Sep/12  Updated: 08/Nov/16

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

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





[CLJS-434] ClojureScript compiler prepends "self__" to defmulti forms when metadata in form of ^:field. Created: 01/Dec/12  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Andrew Mcveigh Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug
Environment:

Mac OS X (10.7), java version "1.6.0_37", leiningen 2 preview 10, cljsbuild 0.2.9.
clojure/clojurescript master 01 December 2012 - 5ac1503



 Description   

Using the def form, with the specific metadata ^:field causes the cljs compiler
to prepend "self__" to the output js form.

The browser (latest chrome/firefox) does not recognize "self__".

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

https://gist.github.com/4185793



 Comments   
Comment by Brandon Bloom [ 01/Dec/12 5:37 PM ]

code tags

Comment by David Nolen [ 20/Jan/13 12:54 AM ]

This one is a bit annoying. We should probably use namespaced keywords internally.





[CLJS-485] clojure.string/replace ignores regex flags Created: 12/Mar/13  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Esa Virtanen Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: bug, patch, test

Attachments: Text File 0001-Take-regex-flags-m-i-into-account-in-clojure.string-.patch     Text File CLJS-485.patch    
Patch: Code and Test

 Description   

The replace function in namespace clojure.string ignores regex flag provided in the match pattern. For example:

CLJS
clojure.string/replace "I am NOT matched" #"(?i)not " "")
=> "I am NOT matched"
CLJ
clojure.string/replace "I am NOT matched" #"(?i)not " "")
=> "I am matched"

The attached patch fixes this by parsing the m and i flags, if set, from the match object, instead of explicitly setting only "g".



 Comments   
Comment by Chas Emerick [ 19/Mar/14 9:29 AM ]

I can confirm the bug. The attached patch applies cleanly, and works as expected.

Esa, sorry for the long delay (this one must have slipped through the cracks)! Could you please submit a contributor's agreement, so that your patch can be merged? More info is here:

http://clojure.org/contributing

Comment by lvh [ 26/Jul/15 5:56 PM ]

I got bit by this bug. Working on figuring out if I can sign that agreement.

Comment by lvh [ 27/Jul/15 11:55 AM ]

This is a duplicate of CLJS-794.

Comment by Jake McCrary [ 04/Feb/16 6:58 PM ]

This patch changes string/replace-all to respect flags that were set on regexp passed as an argument.

I originally attached this to CLJS-794 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.

I've signed a contributors agreement.

Comment by Mike Fikes [ 04/Feb/16 9:31 PM ]

There is a "sticky" flag y that could be conveyed.

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-regexp.prototype.sticky

Comment by Jake McCrary [ 06/Feb/16 10:50 AM ]

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.

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?

Comment by Mike Fikes [ 06/Feb/16 12:51 PM ]

One thought: Whatever this is exercising passes on recent versions of V8, JavaScriptCore, SpiderMonkey, Nashorn, and ChakraCore: https://github.com/clojure/clojurescript/blob/628d957f3ecabf8d26d57665abdef3dea765151e/src/test/cljs/cljs/core_test.cljs#L1472

It does seem tricky to write a robust RegExp clone implementation, and if you do some googling you see people dealing with u and y as special cases. The patch seemed OK to me with respect to this, but I'm not a JavaScript expert.





[CLJS-773] Use unchecked-*-int functions for real 32-bit math Created: 26/Feb/14  Updated: 08/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Francis Avila Assignee: Francis Avila
Resolution: Unresolved Votes: 0
Labels: numerics
Environment:

r2173



 Description   

Currently the unchecked-* functions and macros simply alias the primitive js operators. It would be nice if the unchecked-*-int family of functions and macros implemented C/Java-like signed int operations with silent overflows (just like in Clojure) using asm.js coersion idioms. This should also allow us to share such code between clojure and clojurescript without worrying about their different numerics.

A use case is that porting hash algorithms from java to clojurescript is trickier and more verbose than it needs to be.



 Comments   
Comment by David Nolen [ 08/May/14 6:43 PM ]

This sounds interesting, would like to see more thoughts on approach, benchmarks etc.

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

Bump, this enhancements sound simple & fine.

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

I'll have time to do this in about a week. The implementation is straightforward (basically use xor 0 everywhere). The goal is correctness, but I expect performance to be as good as or better than it is now on most platforms. I'm not sure if advanced mode will drop intermediate truncations or what impact this has on performance.

Some higher-level numeric analysis using the asm.js type system is possible but I doubt it's worth it.

Comment by Francis Avila [ 16/Mar/15 11:14 AM ]

I completely forgot about this, sorry. I see you have scheduled it for the "next" release. Are you assigning it as well or will you still accept a patch?

Comment by David Nolen [ 16/Mar/15 11:26 AM ]

Be my guest





[CLJS-794] RegExp flags are being dropped by `string/replace` Created: 09/Apr/14  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Peter Taoussanis Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None

Attachments: Text File CLJS-794.patch    

 Description   

`clojure.string/replace` accepts either a string or pattern argument to match against.

For pattern arguments, the current implementation discards the original RegExp and creates a new one:
`(.replace s (js/RegExp. (.-source match) "g") replacement)`

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".

Can I submit a patch that'll check for and preserve other (i/m/y) flags?

Thanks



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

A patch is welcome for this. Thanks.

Comment by lvh [ 27/Jul/15 11:55 AM ]

This appears to be identical to CLJS-485, which has a patch (by someone who hasn't signed the CLA yet).

Comment by Jake McCrary [ 04/Feb/16 6:43 PM ]

This patch changes string/replace-all to respect flags that were set on regexp passed as an argument.





[CLJS-871] .-default property access returns nil Created: 11/Oct/14  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Joel Holdbrooks Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None

Attachments: Text File 871.patch     Text File 871.patch    
Patch: Code and Test

 Description   

Types defined with deftype/defrecord which have a default field will incorrectly return nil with property access. The following example will return nil.

(deftype Foo [default])

(let [foo (Foo. "bar")]
  (.-default foo))


 Comments   
Comment by Joel Holdbrooks [ 13/Oct/14 4:19 PM ]

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.

Comment by Joel Holdbrooks [ 13/Oct/14 9:41 PM ]

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 .-default it is any field name that is also a JavaScript identifier (eg. public, private, if).

Comment by David Nolen [ 14/Oct/14 5:26 AM ]

Please lift js-reserved and any helpers like munge into the shared namespace cljs.util so that logic an be shared and hard coding avoided. Thanks.

Comment by Joel Holdbrooks [ 14/Oct/14 5:03 PM ]

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.

Comment by David Nolen [ 14/Oct/14 6:06 PM ]

I'm sure, I'd like to avoid this kind of code duping. Cleaner in the end and better moving forward.

Comment by Joel Holdbrooks [ 18/Mar/15 11:43 AM ]

Updated to use new refactorings

Comment by David Nolen [ 18/Mar/15 11:46 AM ]

The warning is not desirable. Instead we should just munge and ensure property access always works.





[CLJS-994] print a warning when :externs file paths can't be found. Created: 30/Jan/15  Updated: 08/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Crispin Wellington Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: cljs, enhancement, errormsgs, patch,
Environment:

Linux 64bit

java version "1.7.0_65"
OpenJDK Runtime Environment (IcedTea 2.5.3) (7u71-2.5.3-0ubuntu0.14.04.1)
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)


Attachments: Text File clojurescript-extern-missing-warning.patch    
Patch: Code

 Description   

clojurescript silently ignores missing externs files possibly leading a developer to chase their tail.

Presently it can be very confusing using advanced compilation if you have made a mistake in the path name of one of your :externs files. This patch makes the compiler print a warning on stderr so you can quickly determine the cause of the broken advanced compilation output.

As a side effect, when doing a basic lein-cljsbuild a warning is always printed:

```
WARNING: js resource path closure-js/externs does not exist
```

This is because lein-cljsbuild quietly adds this extra path to your :externs listing without you knowing.



 Comments   
Comment by David Nolen [ 31/Jan/15 1:59 PM ]

You need to bind *out* to *err*, or just print to it directly a la cljs.util/debug-prn.

Comment by Crispin Wellington [ 31/Jan/15 7:30 PM ]

I did bind out to err. Check the patch.

Comment by David Nolen [ 01/Feb/15 12:30 PM ]

Crispin, oops sorry you are correct. Thanks.

Comment by David Nolen [ 13/Mar/15 7:33 AM ]

fixed https://github.com/clojure/clojurescript/commit/5f66a78bf469a9875e51aa39c29d3e66ce890eb4

Comment by David Nolen [ 14/Mar/15 5:55 AM ]

The solution does not work for cljsbuild. It's unclear why there so much machinery in place over the approach taken for deps.clj.

Comment by David Nolen [ 15/Mar/15 10:37 AM ]

Stalled on this cljsbuild issue https://github.com/emezeske/lein-cljsbuild/issues/383

Comment by Crispin Wellington [ 23/Mar/15 2:50 AM ]

This lein-cljsbuild issue is what made me make it just a warning initially, and not a hard error like raising IllegalArgumentException does. Though I agree it should be a hard error. If we start with a warning, it enables the immediate problem for the developer to be resolved, and leaves a wart that the cljs-build project can then see that need fixing on their end. Then when that end is fixed it could be made a hard error. If cljsbuild is fixed fairly soon then all is well, but if it takes a long time, a warning might be a good first step.





[CLJS-1070] top-level boolean inference does not work Created: 28/Feb/15  Updated: 08/Nov/16

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

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


 Description   

Problem for using boolean Closure defines



 Comments   
Comment by Francis Avila [ 30/Mar/15 12:02 PM ]

I am unsure if this is the same issue, but forms like ^boolean (js/isFinite n) also do not seem to analyze correctly: if, and, and or will still emit a call to truth_.





[CLJS-1125] Simple corrupted compiled file detection Created: 16/Mar/15  Updated: 08/Nov/16

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

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


 Description   

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.






[CLJS-1127] validate compiled file written to disk Created: 16/Mar/15  Updated: 08/Nov/16

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

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


 Description   

If we validate the file written to disk then we can catch common error of running multiple build processes and abort.






[CLJS-1141] memoization of js-dependency-index and get-upstream-deps needs knobs Created: 18/Mar/15  Updated: 08/Nov/16

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

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

Attachments: Text File CLJS_1141.patch     Text File CLJS-1141-with-js-dep-caching-latest.patch    

 Description   

knobs should be exposed for more dynamic compilation environments like Figwheel which may desire to add dependencies to the classpath on the fly.



 Comments   
Comment by Bruce Hauman [ 21/Mar/15 3:51 PM ]

A patch that caches upstream dependencies in the compiler env.

Comment by Bruce Hauman [ 21/Mar/15 3:59 PM ]

Actually I'm going to submit another patch that includes the memoize calls in js-deps.

Comment by Bruce Hauman [ 28/Mar/15 12:50 PM ]

New patch that moves cljs.js-deps memoization to current env/compiler as well as get-upstream-deps.

Unfortunately there is a circular dep between cljs.env and cljs.js-deps, if we want to cache in env/compiler. I overcame this with a resolve.

Compile performance is either completely unchanged or slightly improved based on several test runs.

Comment by Bruce Hauman [ 28/Mar/15 2:22 PM ]

Hold off on this. Its not behaving as expected. Doesn't seem to be caching in certain situations.

Comment by David Nolen [ 28/Mar/15 2:26 PM ]

Thanks for the update. This will definitely not land until after the pending REPL/piggieback release anyhow.

Comment by Bruce Hauman [ 28/Mar/15 2:44 PM ]

Yeah there is an obvious bug and a subtle one. Hopefully will finish it up soonish.

Comment by Bruce Hauman [ 28/Mar/15 3:43 PM ]

Alright, this latest patch works. There was a subtle memoizing nil value bug.





[CLJS-1147] reconnect logic for browser REPLs Created: 18/Mar/15  Updated: 08/Nov/16

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

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


 Description   

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.



 Comments   
Comment by David Nolen [ 21/Mar/15 8:56 PM ]

This is firmly a major nice-to-have, but not a blocker.





[CLJS-1128] Describe internationalization strategies via Google Closure on the wiki Created: 16/Mar/15  Updated: 08/Nov/16

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

Type: Task Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: documentation, newbie


 Description   

This can be done via Google Closure defines or via pulling a specific locale. A page should document how this can be done.






[CLJS-1129] :modules tutorial for wiki Created: 16/Mar/15  Updated: 08/Nov/16

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

Type: Task Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: documentation, newbie


 Description   

The documentation is nice but something that walks people through the steps would be nicer.






[CLJS-1133] REPL require results in warnings to be emitted twice Created: 17/Mar/15  Updated: 08/Nov/16

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

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

Quick Start Browser REPL with :watch off



 Description   

Run through the Quick Start and go down through to the Browser REPL portion (https://github.com/clojure/clojurescript/wiki/Quick-Start#browser-repl), but exclude the :watch option from repl.clj.

Then further down, where the new symbol is introduced

;; ADDED
(defn foo [a b]
  (+ a b))

instead cause some duplicate symbols to be introduced in order to provoke compiler warnings:

(def a 1)
(def a 1)

(defn foo [a b]
  (+ a b))
(defn foo [a b]
  (+ a b))

Then evaluate the require statement in the tutorial and observe that the warnings are emitted twice:

ClojureScript:cljs.user> (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





[CLJS-1134] Lift protocols from cljs.closure into cljs.protocols ns Created: 17/Mar/15  Updated: 08/Nov/16

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

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


 Description   

This is task towards presenting a stable API to users without reaching into the implementation namespaces.






[CLJS-1136] Initial require fails to fully load added symbols Created: 17/Mar/15  Updated: 08/Nov/16

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

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

Quick Start Browser REPL (OS X / Safari)



 Description   

In the Quick Start, a portion runs the user through adding a symbol (a function named foo) and then requiring the namespace and using that symbol. I'm finding that require fails and that I need to add the :reload directive.

To reproduce:

  1. Run through the Quick Start up through the browser REPL section.
  2. Set src/hello_world/core.cljs so that it does not have the foo function defined.
  3. Remove the out directory: rm -rf out
  4. Start up the REPL: rlwrap java -cp cljs.jar:src clojure.main repl.clj
  5. Connect Safari by going to http://localhost:9000
  6. Show the error console in Safari. (You'll see Hello world.)
  7. Run tail -f out/watch.log
  8. Add the foo function that adds a b to src/hello_world/core.cljs and save it.
  9. Observe that watch.log reflects recompilation
  10. Do {{ (require '[hello-world.core :as hello]) }}
  11. Do {{ (hello/foo 2 3) }}

At this point you will get:
TypeError: undefined is not an object (evaluating 'hello_world.core.foo.call')

But:

ClojureScript:cljs.user> (ns-interns 'hello-world.core)
{foo #'hello-world.core/foo, conn #'hello-world.core/conn}
ClojureScript:cljs.user> (source hello/foo)
(defn foo [a b]
  (+ a b))
nil

Now, if you :reload

ClojureScript:cljs.user> (require '[hello-world.core :as hello] :reload)
nil
ClojureScript:cljs.user> (hello/foo 2 3)
5


 Comments   
Comment by Mike Fikes [ 17/Mar/15 11:30 AM ]

Prior to step 8:

ClojureScript:cljs.user> (ns-interns 'hello-world.core)
{}

Between steps 9 and 10:

ClojureScript:cljs.user> (ns-interns 'hello-world.core)
{foo #'hello-world.core/foo, conn #'hello-world.core/conn}

My guess: Watching is causing symbols to be interned, but not usable, and this is interfering with require forcing you to include :reload.

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

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 :reload. 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.





[CLJS-1139] Repeated applications of `ns` form at the REPL are not additive Created: 17/Mar/15  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Michael Griffiths Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Quick start guide with Node REPL



 Description   

In a Clojure REPL, it is possible to declare the same namespace again, without existing namespaces aliases being altered or removed:

user=> (ns my-test-ns.core (:require [clojure.string :as string]))
nil
my-test-ns.core=> (def a string/blank?)
#'my-test-ns.core/a
my-test-ns.core=> (ns my-test-ns.core)
nil
my-test-ns.core=> (def a string/blank?)
#'my-test-ns.core/a
my-test-ns.core=>

ClojureScript REPLs do not behave in the same way:

ClojureScript:cljs.user> (ns my-test-ns.core (:require [clojure.string :as string]))
true
ClojureScript:my-test-ns.core> (def a string/blank?)
#<function clojure$string$blank_QMARK_(s){
return goog.string.isEmptySafe(s);
}>
ClojureScript:my-test-ns.core> (ns my-test-ns.core)
nil
ClojureScript:my-test-ns.core> (def a string/blank?)
WARNING: No such namespace: string, could not locate string.cljs at line 1 <cljs repl>
WARNING: Use of undeclared Var string/blank? at line 1 <cljs repl>
repl:13
throw e__3919__auto__;
      ^
ReferenceError: string is not defined
    at repl:1:109
    at repl:9:3
    at repl:14:4
    at Object.exports.runInThisContext (vm.js:74:17)
    at Domain.<anonymous> ([stdin]:41:34)
    at Domain.run (domain.js:197:16)
    at Socket.<anonymous> ([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>





[CLJS-1159] compiled files with warnings that otherwise don't need recompilation will not emit warnings on the next compile Created: 23/Mar/15  Updated: 08/Nov/16

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

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


 Description   

The aggressive caching approach is odds with warning visibility. It probably makes sense for a compiled file with warnings to always return true for requires-compilation?.






[CLJS-1174] Simple warning if a namespace with dashes not found but a file path with dashes exists Created: 27/Mar/15  Updated: 08/Nov/16

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

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





[CLJS-1195] generic reusable command line argument parsing for REPLs Created: 10/Apr/15  Updated: 08/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Jason Courcoux
Resolution: Unresolved Votes: 0
Labels: newbie


 Description   

REPLs are more or less started in the same way and all the builtin ones provide a -main entry point. We should supply reusable command line argument parsing that any REPL can use to get standard command line driven start.



 Comments   
Comment by Jason Courcoux [ 30/Sep/16 3:27 AM ]

Just wanted to capture my initial thoughts in case I'm going down the wrong road, or overthinking it and someone wants to point me in a different direction. I can see the following options for parsing the command line arguments - in no particular order:

1) Reuse a third party such as clojure/tools.cli

  • Less to maintain within the ClojueScript codebase itself.
  • Supports GNU option parsing conventions
  • Extra dependency - Guessing this is a a definite no for various reasons, but don't want to assume anything.
  • Is it over complicated for our needs here?

2) Reuse something in the java platform - looks like there is a class sun.tools.jar.CommandLine which has very basic functionality for parsing command line arguments.

  • Already in the Java platform, although I believe this is probably only in the JDK so probably no good for this use case.
  • Very limited support - would be easier to replicate the functionality in clojure code.

3) Use the clojure reader to just read in clojure data

  • Nice and simple, and reusing something that already exists
  • Arguments would be in the same format as they are now
  • No validation of parameters passed in.

4) Custom parsing of arguments - wondering if we could do something with clojure spec and allow repls to pass a spec which could be used to infer how to parse/validate the data (e.g. for port number is it an int or string).

  • Leveraging spec gives repls a mechanism to specify constraints, and can get clear errors out
  • Can be more flexible in the arguments accepted - i.e. --port "9000" and --port 9000 could both be valid
  • I've not done much with spec so although I think this sounds feasible I'm not 100%

I think I'm going to explore option 4, and I'll update as I go.

Comment by David Nolen [ 30/Sep/16 6:09 AM ]

Thanks for writing this up. 1) tools.cli is not a bad idea but do we need it. 3) seems Clojure-y - we just want typical CLI support. 4) Clojure 1.9 is alpha we don't want a dependency on this.

My original thought was to just replicate what clojure.main does - I don't see why we need anything more.

Comment by Jason Courcoux [ 30/Sep/16 9:45 AM ]

Thanks for the quick response. I've had a look at clojure.main, and as far as I can tell it doesn't do anything in the way of generic parsing of arguments - The main function dispatches based on some known options (repl/main/help etc) and passes the rest of the arguments through - in each case it just binds the arguments to command-line-args which may or may not get parsed/accessed at a later point either during startup, or from the repl session - neither of these seem to be what this Jira is asking for, unless I've misunderstood.

Just so I'm 100% on what's being asked here - this ticket is for parsing repl environment options, i.e. for the browser repl the options would be host/port/working-dir/serve-static etc, and the parsing would need to handle strings/int/boolean values etc.

I'm conscious you're probably very busy, I'm almost certainly missing something, and don't want to take up too much of your time, so if you tell me it's there in clojure.main I'll keep digging until I find it.

Comment by David Nolen [ 30/Sep/16 10:48 AM ]

We're not at all interested in exposing all the options via command line flags. The first step is simply mirroring Clojure's REPL options that make sense. For all the CLJS REPL specific stuff a flag which takes string of EDN or an EDN config file is fine.





[CLJS-1207] Emit a warning if multiple resources found for a ClojureScript namespace Created: 15/Apr/15  Updated: 08/Nov/16

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

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


 Description   

We should emit a simple warning if a namespace doesn't not appear to be unique on the classpath.






[CLJS-1297] defrecord does not emit IKVReduce protocol Created: 03/Jun/15  Updated: 08/Nov/16

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

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

Attachments: Text File CLJS-1297-19-July-2015.patch    

 Description   

Records are maps and in Clojure they support reduce-kv (IKVReduce protocol).
This is not true in ClojureScript:

(defrecord Foobar [x y])
 (reduce-kv assoc {} (Foobar. 1 2))

Fails wit Error: No protocol method IKVReduce.-kv-reduce defined for type : [object Object]



 Comments   
Comment by David Nolen [ 03/Jun/15 7:25 PM ]

Just seems like an oversight. Patch welcome, this one is a relatively easy one.

Comment by Daniel Skarda [ 04/Jun/15 2:53 AM ]

OK

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?

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?

;;clojure/src/clj/clojure/core.clj:6523
;;slow path default
clojure.lang.IPersistentMap
(kv-reduce 
  [amap f init]
  (reduce (fn [ret [k v]] (f ret k v)) init amap))
Comment by David Nolen [ 04/Jun/15 9:05 AM ]

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.

Comment by Samuel Miller [ 16/Jul/15 10:39 PM ]

Mind if I take this as my first cljs bug? Poking around quickly I think I know what needs to happen.

Comment by David Nolen [ 17/Jul/15 5:21 AM ]

Sure! Have you submitted your CA yet?

Comment by Samuel Miller [ 17/Jul/15 7:13 PM ]

Yes, I did yesterday.

Comment by Samuel Miller [ 20/Jul/15 9:52 PM ]

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. Also added a test for reduce-kv on records.

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.

Comment by Sebastian Bensusan [ 23/Jul/15 6:45 PM ]

Experience report:

I just tested the patch in the Node Repl and it seems to work:

cljs.user=> (defrecord A [a b])
cljs.user/A
cljs.user=> (reduce-kv (fn [m k v] (assoc m k (inc v))) {} (A. 1 2))
{:a 2, :b 3}

and the provided tests passed in Spidermonkey, V8, and Nashorn (I don't have JSC installed).

For completeness: before applying the patch the same code fails with:

Error: No protocol method IKVReduce.-kv-reduce defined for type : [object Object]
Comment by David Nolen [ 10/Aug/15 10:22 PM ]

Is this the same approach taken by Clojure?

Comment by Samuel Miller [ 10/Aug/15 10:36 PM ]

You can see the relevant current Clojure code here...
https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6526
I think it is the same. I literally just tried to translate it over into CLJS. I might of understood something wrong though.

Comment by David Nolen [ 11/Aug/15 6:10 AM ]

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.

Comment by Samuel Miller [ 11/Aug/15 8:48 PM ]

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.

I can also spend some time trying to make a more performant version.

Comment by António Nuno Monteiro [ 27/Jul/16 7:38 AM ]

Confirmed that Clojure uses the slow path via the IPersistentMap implementation in defrecord
https://github.com/clojure/clojure/blob/d920ad/src/clj/clojure/core.clj#L6712

Patch still applies and can also confirm it works for me.





[CLJS-1300] REPLs do no write out updated deps.js when compiling files Created: 05/Jun/15  Updated: 08/Nov/16

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

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

Attachments: Text File cljs-1300.patch    
Patch: Code

 Description   

For example a user may edit a file including a new dependency. This will work at the REPL but if a browser refresh is made the emitted goog.require will fail due to the initial deps.js file being stale.



 Comments   
Comment by ewen grosjean [ 05/Dec/15 4:15 PM ]

load-file is broken into 4 sub-functions:
repl-compile-cljs: compile the cljs file beeing loaded
repl-cljs-on-disk: ensures all dependencies are on disk
refresh-cljs-deps: refreshes the cljs_deps.js file
repl-eval-compiled: eval the compiled file

Comment by David Nolen [ 05/Dec/15 9:02 PM ]

Thanks will review.

Comment by Mike Fikes [ 31/Jan/16 3:25 PM ]

cljs-1300.patch no longer applies on master





[CLJS-1328] Support defrecord reader tags Created: 04/Jul/15  Updated: 08/Nov/16

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

Type: Enhancement Priority: Major
Reporter: Herwig Hochleitner Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: reader, readertags


 Description   

Currently, defrecord instances print similar to how they do in clojure

> (pr-str (garden.units/px 5))
#garden.types.CSSUnit{:unit :px, :magnitude 5}

This representation cannot be read by the compiler, nor at runtime by cljs.reader/read-string

> #garden.types.CSSUnit{:unit :px, :magnitude 5}
clojure.lang.ExceptionInfo: garden.types.CSSUnit {:type :reader-exception, :line 1, :column 22, :file "NO_SOURCE_FILE"}
...
> (cljs.reader/read-string "#garden.types.CSSUnit{:unit :px, :magnitude 5}")
#<Error: Could not find tag parser for garden.types.CSSUnit in ("inst" "uuid" "queue" "js")>
...

Analysis

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.

Record literals

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.
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.

EDIT: Record literals can also go into the constant pool

cljs.reader

To play well with minification, the ^:export annotation could be reused on defrecords, to publish the corresponding reader tag to cljs.reader.

Related Tickets



 Comments   
Comment by David Nolen [ 08/Jul/15 12:00 PM ]

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.

I'm all for this enhancement.





[CLJS-1373] Generalize CLJS-1324, check invokes of all IFn implementors Created: 28/Jul/15  Updated: 08/Nov/16

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

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


 Description   

We currently track all IFn implementors but in order to do arity checking of statically analyzeable invokes of keywords, vector, etc. we need to do a bit more. extend-type should update the type in the compiler state with :method-params :max-fixed-arity and :variadic. Then we can just reuse the existing checks in cljs.analyzer/parse-invoke.






[CLJS-1402] Source Mapping Closure Error Logger Created: 08/Aug/15  Updated: 08/Nov/16

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

Type: Enhancement Priority: Major
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: type-check


 Description   

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.






[CLJS-1222] Sequence of a stateful transducer is producing the wrong answer Created: 24/Apr/15  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Lucas Cavalcanti Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, cljs, collections
Environment:

OSX 10.10.3, java 1.8.0-ea-b124



 Description   

I'm producing more than one element on the 1-arity of the transducer, and sequence is only considering the last one.

Here is the transducer and the tests that fail for sequence:

(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->clj a)))
             (.shift a)
             (recur))))
        ([result input]
         (.push a input)
         (if (== n (.-length a))
           (let [v (vec (js->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]))))


 Comments   
Comment by Lucas Cavalcanti [ 24/Apr/15 11:18 AM ]

I could make it work by recurring on the result.

([result]
  (loop [res result]
    (if (not-empty a)
      (let [v (vec (js->clj a))]
        (.shift a)
        (recur (rf res v)))
      res)))

even so it's weird that the previous version behaves differently on core.async and sequences in cljs and clj

Comment by David Nolen [ 26/Apr/15 4:04 AM ]

Please demonstrate the problem without core.async. Thanks.

Comment by Lucas Cavalcanti [ 26/Apr/15 7:32 PM ]

Hi,

the last test I posted on the ticket, fails in cljs, but not in clj:

;;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]))))
Comment by David Nolen [ 27/Apr/15 7:43 AM ]

I've removed the core.async bits from the description to clarify the issue.

Comment by David Nolen [ 10/May/15 2:40 PM ]

The implementation of sliding-window above does not appear to be correct, it doesn't return the result. This ticket needs more information.

Comment by Lucas Cavalcanti [ 10/May/15 3:51 PM ]

As I said on http://dev.clojure.org/jira/browse/CLJS-1222?focusedCommentId=38620&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-38620

changing the 1-arity of the sliding-window to that fixes the transducer.

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.





[CLJS-1237] ns-unmap doesn't work on refers from cljs.core Created: 01/May/15  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Chouser Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: ns-unmap

Attachments: Text File 0001-CLJS-1237-ns-unmap-adds-to-namespace-s-excludes.patch     Text File 0002-CLJS-1237-ns-unmap-adds-to-namespace-s-excludes.patch    
Patch: Code

 Description   

In ClojureScript, using ns-unmap on a symbol from cljs.core doesn't exclude it from the current namespace. Note that both a function and a macro still exist, even after unmapping:

To quit, type: :cljs/quit  
cljs.user=> (ns-unmap 'cljs.user 'when) ;; macro
true  
cljs.user=> (ns-unmap 'cljs.user 'not)  ;; function
true  
cljs.user=> (when 1 2)  
2  
cljs.user=> (not false)  
true  

This differs from the behavior of Clojure's ns-unmap. Note the appropriate errors when attempting to use unmapped symbols:

Clojure 1.7.0-beta1
user=> (ns-unmap 'user 'when) ;; macro
nil
user=> (ns-unmap 'user 'not)  ;; function
nil
user=> (when 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: when in this context, compiling:(NO_SOURCE_PATH:11:1) 
user=> (not false)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: not in this context, compiling:(NO_SOURCE_PATH:12:1) 

Somehow ClojureScript's ns-unmap needs to add the symbol to the current namespace's :excludes set. Note that the def special form does this already (after it displays a warning).

We have two solutions. 0001 extends the ns form's :merge behavior to support :excludes, and then uses this in ns-unmap. If the enhancement to ns isn't wanted, patch 0002 changes ns-unmap to update :excludes directly.



 Comments   
Comment by David Nolen [ 05/May/15 7:23 AM ]

The second patch is preferred. However it seems the second patch is too permissive. The :excludes logic should only be applied if the symbol identifies a core macro or fn.

Comment by Chouser [ 05/May/15 3:46 PM ]

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?

Comment by David Nolen [ 05/May/15 4:08 PM ]

New ticket to fix the bug that :exclude doesn't check the symbol list for cljs.core declared vars, and an updated patch here please.





[CLJS-1238] Setting *main-cli-fn* when using :target :nodejs shouldn't be manditory Created: 01/May/15  Updated: 08/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Jeremy Shoemaker Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None

Attachments: Text File nodejs-main-cli-fn.patch    
Patch: Code

 Description   

Currently, when you use :target :nodejs in the build options for ClojureScript, the resulting code requires you to set *main-cli-fn* to a function.

This prevents someone from writing a library that can be used by JavaScript developers because it forces code execution on require. 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 npm install or npm link. 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.

I don't see any reason why you should be forced to set *main-cli-fn* and so I'm suggesting making it optional.

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.

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.



 Comments   
Comment by Jeremy Shoemaker [ 01/May/15 7:27 PM ]

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.

Comment by Ning Sun [ 18/Feb/16 4:08 AM ]

+1.

I was working on a clojurescript library and going to build it as a node library. Currently blocked by this.

Comment by Mike Fikes [ 20/Feb/16 8:07 AM ]

Patch no longer applies.





[CLJS-1271] Missing warning when assigning namespaces via def Created: 17/May/15  Updated: 08/Nov/16

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

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


 Description   

Currently you can assign a Closure namespace to a var without getting a warning.

Minimal sample:

(ns import-names.core
  (:import [goog debug]))

(def debug goog.debug)


 Comments   
Comment by David Nolen [ 29/May/15 12:30 PM ]

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.

Comment by Sebastian Bensusan [ 29/May/15 12:46 PM ]

We should check that :require ed and :import ed namespaces are not used as values and then warn about it.





[CLJS-1286] REPL environment should be able to provide advice if source mapping fails Created: 23/May/15  Updated: 08/Nov/16

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

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


 Description   

For example browser REPL will often need users to supply :host-port, :host, and :asset-path in order to correctly parse files from stacktraces.






[CLJS-1315] Warning on Google Closure enum property access with / Created: 18/Jun/15  Updated: 08/Nov/16

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

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


 Description   

Edge case in / usage, EventType/CLICK 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.






[CLJS-1412] Add JSDoc type information to individual IFn methods Created: 10/Aug/15  Updated: 08/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: type-check


 Description   

Propagate user supplied docstring type information to the various fn arities so that more code may be checked.






[CLJS-1415] Handling JSDoc param name [x] optional syntax Created: 10/Aug/15  Updated: 08/Nov/16

Status: In Progress
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: Next

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: type-check





[CLJS-1443] ES6 Module Processing at individual :foreign-lib spec Created: 09/Sep/15  Updated: 08/Nov/16

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

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


 Description   

ES6 module processing could probably benefit from processing at the individual :foreign-lib spec. Brings up questions wrt. source maps and merged source maps when applying other optimization settings.






[CLJS-1446] autodoc + gh-pages for cljs.*.api namespaces Created: 11/Sep/15  Updated: 08/Nov/16

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

Type: Task Priority: Major
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: newbie


 Comments   
Comment by W. David Jarvis [ 11/Sep/15 6:07 PM ]

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 here but it doesn't look like it's seen any movement in nearly two years.

Comment by Tom Faulhaber [ 13/Sep/15 2:26 PM ]

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 issue in autodoc 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.

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

This ticket is about generating docs for Clojure code. Getting autodoc to work for ClojureScript files is worth pursuing but unrelated to this ticket.

Comment by Sebastian Bensusan [ 11/Oct/15 5:54 PM ]

I took at stab at this and only got it running using autodoc-0.9.0-standalone.jar from the command line. My results are not useful at all but those issues should be sorted out in autodoc.

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?

Comment by Tom Faulhaber [ 12/Oct/15 12:37 AM ]

Oh, I did misunderstand this and then didn't see David Nolen'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!)

Comment by Tom Faulhaber [ 02/Jul/16 2:14 AM ]

I have just closed the blocking issue in autodoc Issue 21, andSebastian Bensusan has successfully built a version of doc for the src/main/clojure/... stuff.

The next step is to flesh out what we want to push to http://clojure.github.io/clojurescript. I don't think that this is too hard. Then we can integrate it with the autodoc robot and get automatic updates.





[CLJS-1447] IFn implementors have a broken call implementation, all args after 20th argument should be collected into a seq Created: 11/Sep/15  Updated: 08/Nov/16

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

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


 Description   

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.



 Comments   
Comment by François De Serres [ 18/Jun/16 9:13 AM ]

we should transform the 21st arity into a var args signature

Unless misunderstanding, can't do that. Var args sigs aren't allowed in protocols.

we should not allow arities above 21 args

Emitting an analyzer warning is what you want?

Comment by Antonin Hildebrand [ 05/Jul/16 6:07 PM ]

I believe I hit this problem in my code using core.async[1].

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.

[1] https://github.com/binaryage/dirac/commit/cce56470975a287c0164e6f79cd525d6ed27a543





[CLJS-1501] Add :parallel-build support to REPLs Created: 05/Dec/15  Updated: 08/Nov/16

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

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


 Description   

The :parallel-build option does not currently work in REPLs due to the implementation of cljs.repl/load-namespace






[CLJS-1419] enhance numeric inference, if + number? test on local var should tag local var in the successful branch Created: 12/Aug/15  Updated: 08/Nov/16

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

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


 Comments   
Comment by David Nolen [ 12/Aug/15 6:44 AM ]

One small complication is dealing with and as it has an optimizing case.





[CLJS-1485] Error when requiring `goog` namespace in a ns declaration Created: 10/Nov/15  Updated: 08/Nov/16

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

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


 Description   

I wanted to use functions from goog namespace although--as I found out later, I didn't have to because goog is already exists in my namespace. So, I put (:require [goog]) in a ns declaration. Then, when I tried to reload that particular namespace by doing :require :reload in a cljs repl, I got:

Error: Namespace "x.x.x" already declared.

Doing :require :reload again in the cljs repl makes the repl throws

Error: Namespace "cljs.user" already declared.
(NO_SOURCE_FILE)
(out/goog/base.js:273:40)

I tested the steps below using clojurescript 1.7.145 and 1.7.170.

Here are the steps to reproduce which are taken from clojurescript quickstart-browser repl section:

1. Download the standalone clojurescript 1.7.170 jar https://github.com/clojure/clojurescript/releases/download/r1.7.170/cljs.jar

2. Create a directory hello_world and copy the JAR into that directory, then from inside the hello_world directory:

mkdir -p src/hello_world;touch repl.clj;touch index.html;touch src/hello_world/core.cljs

3. repl.clj content

(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")

4. index.html content

<html>
    <body>
        <script type="text/javascript" src="out/main.js"></script>
    </body>
</html>

5. src/hello_world/core.cljs content

(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))

6. run clojurescript repl

java -cp cljs.jar:src clojure.main repl.clj

7. Open http://localhost:9000 in browser (I use google chrome). Open javascript console.

8. enter expression below in the clojurescript repl

(require '[hello-world.core :as hello] :reload)

10. Look the browser javascript console. Nothing new shown.

11. Quit from the repl using :cljs/quit

12. Add [goog] in ns declaration in src/hello_world/core.cljs so that the content of the file becomes:

(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))

13. Run the clojurescript repl again

java -cp cljs.jar:src clojure.main repl.clj

14. Now refresh the http://localhost:9000 in browser. Make sure the javascript console stays open.

13. enter expression below in the clojurescript repl

(require '[hello-world.core :as hello] :reload)
;;=> nil

it just returns nil

15. See the javascript console, it shows

Uncaught Error: Namespace "hello_world.core" already declared.

16. Executing this expression again (require '[hello-world.core :as hello] :reload) shows nothing new in the browser's javascript console while the clojurescript repl throws

Error: Namespace "cljs.user" already declared.
(NO_SOURCE_FILE)
(out/goog/base.js:273:40)





[CLJS-1544] cljs.test REPL reload support Created: 13/Jan/16  Updated: 08/Nov/16

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

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


 Description   

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.






[CLJS-1641] Multi-arity defn copies arguments unnecessarily for all cases Created: 16/May/16  Updated: 08/Nov/16

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

Type: Defect Priority: Minor
Reporter: Stephen Brady Assignee: Stephen Brady
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1641.patch    
Patch: Code

 Description   

Background:

Passing js arguments as a parameter to another function is a known performance issue. Copying arguments to an array addresses this, and this approach has been taken to handle args passing for variadic functions in previous patches such as:
https://github.com/clojure/clojurescript/commit/dccc5d0feab9809cb56bd4d7257599a62232ac0d
https://github.com/clojure/clojurescript/commit/f09bbe62e99e11179dec6286fbb46265c12f4737

This commit (https://github.com/clojure/clojurescript/commit/576fb6e054dd50ec458a3c9e4172a5a0002c7aea) introduced a macro path for `defn` forms.

Current Behavior and Impact:

In the case of multi-arity defn forms, the macro path generates an array copy of the arguments variable regardless of whether it is used or necessary. In the case of multiple arities but no variadic arity, copying arguments is unnecessary as arguments will not be passed to the variadic method for the given function. In the case of multiple arities with a variadic case, an args array copy is needed but should be isolated to that case alone; currently, the array copy is performed before checking the arguments length, causing all cases to incur an (unused) args array copy.

Relevant code: https://github.com/clojure/clojurescript/blob/master/src%2Fmain%2Fclojure%2Fcljs%2Fcore.cljc#L2827-L2843

Recommended Change:

  • Do not perform an args array copy before switching on arguments length
  • Perform an args array copy within the variadic dispatch case

Patch forthcoming.



 Comments   
Comment by David Nolen [ 21/May/16 5:03 PM ]

Thanks! Will take a look.

Comment by David Nolen [ 10/Jun/16 1:32 PM ]

This probably needs to be updated in the compiler as well.

Comment by Stephen Brady [ 10/Jun/16 2:43 PM ]

The compiler already isolates the args to array copying behavior in the variadic case. The unnecessary copying is isolated to the defn macro.

These are the only two calls to `emit-arguments-to-array`:

Variadic function: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/compiler.cljc#L743
Multi-arity with variadic case: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/compiler.cljc#L812

Comment by Francis Avila [ 11/Jun/16 8:33 AM ]

From what I can see copy-arguments is only ever used with an immediately-constructed empty array as the dest in the pattern:

`(let [arr# (array)]
  (copy-arguments arr#)
  ;;...
  )

Perhaps it should change to have the exact same behavior as emit-arguments-to-array, i.e. it should take a start index and expand to the name of the destination array. The advantages of this approach are 1) it can preallocate the array to the correct size and 2) your patch no longer needs a slice call--you can avoid allocating two arrays instead of just one. (These two reasons are why I implemented emit-arguments-to-array the way I did.)

I can't think of a way to implement emit-arguments-to-array as a macro without emitting a wrapping js function which messes up the scope, but you could do this:

(defmacro copy-arguments [dest-arr startslice]
  `(loop [i# 0]
     (when (< i# (alength ~dest-arr))
       (aset ~dest-arr i# (aget (js-arguments) (+ i# startslice)))
       (recur (inc i#)))))

And then at the callsite:

`(let [variadic-args-arr# (make-array (- (alength (js-arguments)) ~maxfa))]
  (copy-arguments variadic-args-arr# ~maxfa)
    (let [argseq# (new ^::ana/no-resolve cljs.core/IndexedSeq
                       variadic-args-arr# 0 nil)]
      ;; ...
    ))

However, there are some bugs around arity handling that the above would not solve: CLJS-1678

Comment by Stephen Brady [ 11/Jun/16 8:27 PM ]

Francis, thanks for commenting on this. The patch that I submitted simply moves where/when `copy-arguments` is called. Other than that, I preserved all other aspects of the existing implementation, including how the array is built up and then made into an IndexedSeq. The line diffing in the patch implies that I changed a lot more than I really did. Agreed with your point that `emit-arguments-to-array` is more efficient and precise. Intentionally, I did not try to alter/improve/correct anything in this patch beyond solving the objective in the issue: not unnecessarily copying arguments.

Glad you've reported CLJS-1678 as I've observed this too. This buggy behavior shows up in several places. Beyond what this issue-patch attempts to address, in general, my observation is that we could probably clear out some under-brush that's accumulated as the compiler has matured with regards to arguments handling and code generated for multi-arity and/or variadic functions, apply / applyTo, and implementations of IFn. Seems like there are several opportunities to emit less javascript, create fewer intermediates, and shorten the call chain.

So to reiterate, this patch - despite its superficial appearance - changes very little and just moves the call to copy-arguments to the appropriate place. The benefit is:

For multi-arity functions with no variadic arity, no code for copying the arguments to an array is emitted at all (which in aggregate turns out to be a decent amount). Obviously, at runtime, no array will be created.

For multi-arity functions with a variadic arity, the code for copying the arguments remains but is isolated to the variadic case, and so if the function is called but will dispatch to one of the fixed arities, again, no array will be created.





[CLJS-1795] Support more options in the `:closure-warnings` compiler option Created: 28/Sep/16  Updated: 08/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: António Nuno Monteiro Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Support more options in the `:closure-warnings` compiler option as per https://github.com/google/closure-compiler/wiki/Warnings#warnings-categories






[CLJS-1745] refer-clojure doesn't pull in previously excluded vars Created: 14/Aug/16  Updated: 08/Nov/16  Resolved: 08/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1745.patch    
Patch: Code

 Description   

Observe this behavior in Clojure:

user=> (ns foo.core (:refer-clojure :exclude [juxt partial]))
nil
foo.core=> juxt
CompilerException java.lang.RuntimeException: Unable to resolve symbol: juxt in this context, compiling:(NO_SOURCE_PATH:0:0)
foo.core=> partial
CompilerException java.lang.RuntimeException: Unable to resolve symbol: partial in this context, compiling:(NO_SOURCE_PATH:0:0)
foo.core=> (refer-clojure :exclude [])
nil
foo.core=> juxt
#object[clojure.core$juxt 0x2f62ea70 "clojure.core$juxt@2f62ea70"]
foo.core=> partial
#object[clojure.core$partial 0x38aa816f "clojure.core$partial@38aa816f"]

Compare with ClojureScript:

$ script/noderepljs
ClojureScript Node.js REPL server listening on 49402
To quit, type: :cljs/quit
cljs.user=> (ns foo.core (:refer-clojure :exclude [juxt partial]))
nil
foo.core=> juxt
nil
foo.core=> partial
nil
foo.core=> (refer-clojure :exclude [])
nil
foo.core=> juxt
nil
foo.core=> partial
nil


 Comments   
Comment by António Nuno Monteiro [ 07/Nov/16 12:57 PM ]

Attached patch with fix.

Comment by David Nolen [ 08/Nov/16 1:32 PM ]

fixed https://github.com/clojure/clojurescript/commit/2fb9d1914a932adc833bd82044551205d5793738





[CLJS-1666] Flag to optionally disable transit analysis cache encoding Created: 03/Jun/16  Updated: 08/Nov/16  Resolved: 08/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: 1.9.36
Fix Version/s: Next

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

Attachments: Text File CLJS-1666-1.patch     Text File CLJS-1666.patch    
Patch: Code

 Description   

We need a flag to explicitly disable the transit encoding - this is to work around code that creates unencodeable forms for one reason or another. EDN had become more lax about encoding random Objects which allowed this stuff to go under the radar in the past.



 Comments   
Comment by Wilker Lúcio da Silva [ 06/Jun/16 9:10 PM ]

I'm having a compilation issue with ClojureScript 1.9.36, I'm writing an app that uses untangled and this file https://github.com/untangled-web/untangled-client/blob/f42088c84b059562a48455a71daa6e4ea08d286c/src/untangled/client/data_fetch.cljs fails to compile with Caused by: java.lang.RuntimeException: java.lang.Exception: Not supported: class cljs.tagged_literals.JSValue this issue doesn't happen with 1.9.14

Comment by David Nolen [ 06/Jun/16 10:06 PM ]

We should investigate whether just handling JSValue + other cases like clojure.lang.Var is good enough.

Comment by David Nolen [ 08/Jun/16 8:53 AM ]

JSValue encoding/decoding landed in master fixing part of the issue. Still need more information about the Var case however.

Comment by António Nuno Monteiro [ 07/Nov/16 3:17 PM ]

Attached patch with fix.

Comment by Thomas Heller [ 07/Nov/16 3:53 PM ]

Will the toggle to :edn not just "hide" a problem?

Say the user somehow manages to break the transit encoding by using custom value. A google search will reveal the solution of switching to :edn. But since the custom value runs through the "default" handler of :edn there is no correct way to re-build it when reading the cache. Instead it will just be a placeholder TaggedValue without meaning. If anyone ever tries to access it we now have a case where it will work without caching but not with a cached value.

I think caching should just gracefully fail instead of adding a broken alternative?

Comment by Thomas Heller [ 08/Nov/16 4:13 AM ]

As per Slack discussion I opened a separate issue to focus on the actual problem.

See: http://dev.clojure.org/jira/browse/CLJS-1843

I still think however that the newly introduced :cache-analysis-format is not useful to the user. If Transit is available it should always be used as it is the "better" option. I'm not sure there is a benefit of letting the user decide other than maybe work around issues that Transit has that EDN might not have. Hiding the actual problem by doing so.

If the cache write "fails" for any reason it should just warn about it instead of failing the build.

Comment by António Nuno Monteiro [ 08/Nov/16 7:44 AM ]

Attached CLJS-1666-1.patch which takes into account feedback obtained in Slack.
Specifically:

  • added validation for the `:cache-analysis-format` option
  • explicit inference of the cache file format via the new function `cache-analysis-ext`
Comment by David Nolen [ 08/Nov/16 12:26 PM ]

fixed https://github.com/clojure/clojurescript/commit/80bbded9527dce6216f36763f23b7e5ebf8930df





[CLJS-1843] EDN analysis cache may write unusable data Created: 08/Nov/16  Updated: 08/Nov/16

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

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


 Description   

EDN has a built-in default writer for all objects, this may cause the cache to write something like

#object[Thing "thing-str"]
that cannot be read to construct an actual Thing instance.

This leads to an issue when trying to use the analysis data since it will contain different things when coming from cache or not.

This issue was highlighted by transit since it has no default writer and didn't know how to encode JSValue. [1] Instead of writing something unusable it failed early.

The cache write should rather gracefully fail (and warn) instead of writing unusable data or exploding.

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






[CLJS-1840] Provide more descriptive error message when invalid libspec detected Created: 06/Nov/16  Updated: 07/Nov/16  Resolved: 07/Nov/16

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

Type: Enhancement Priority: Minor
Reporter: Daniel Compton Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: errormsgs

Attachments: Text File CLJS-1840.patch     Text File CLJS-1841.v1.patch    
Patch: Code and Test

 Description   

When an invalid libspec is detected while compiling, the compiler throws an error which doesn't specify what the invalid libspec is. Combined with the line/column number referring to the start of the file, this can make it difficult to track down what is causing the problem.

I ran into this when an incorrect git merge left the ns spec in an invalid state:

(ns re-frame.fx-test
  (:require
    [cljs.test :refer-macros [is deftest async use-fixtures]]
    [cljs.core.async :as async :refer [<! timeout]]
    [clojure.string :as str]
    [re-frame.core :as re-frame]
    [re-frame.fx]
    [re-frame.interop :refer [set-timeout!]])
    [re-frame.loggers :as log]
  (:require-macros [cljs.core.async.macros :refer [go]]))

Even after looking at the ns form a few times, I still couldn't see what was wrong.

I've attached a patch which prints the invalid libspec in the error message. The new error message should make it much easier to find and fix the problem.



 Comments   
Comment by Daniel Compton [ 06/Nov/16 4:49 PM ]

Updated with ticket number in commit message.

Comment by David Nolen [ 07/Nov/16 2:43 PM ]

fixed https://github.com/clojure/clojurescript/commit/78f6504e1c67c935c283a362ecf6cb5a3766022e





[CLJS-1794] incomplete alias created for namespace cljs.spec warning under advanced compilation Created: 26/Sep/16  Updated: 07/Nov/16  Resolved: 07/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Defect Priority: Major
Reporter: Michael Glaesemann Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

λ lein --version
Leiningen 2.6.1 on Java 1.8.0_45 Java HotSpot(TM) 64-Bit Server VM


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

 Description   

Under advanced compilation, use of cljs.spec can cause analyzer warnings.

out/cljs/analyzer.js:4740: WARNING - incomplete alias created for namespace cljs.spec
var mchk = (function (){var and__6935__auto__ = cljs.spec;
                                                ^

Sep 26, 2016 7:18:00 PM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 0 error(s), 1 warning(s)
Successfully compiled "out/main.js" in 43.391 seconds.


 Comments   
Comment by Michael Glaesemann [ 26/Sep/16 6:28 PM ]

I came across this when upgrading Om from alpha44 to alpha45. The commit that changed the behavior moved to from cljs to cljc for server-side rendering support. (https://github.com/omcljs/om/commit/439802239fdfb95b143cde33df26be7801069bf2)

Test case: https://gist.github.com/grzm/0d2db1d1364daeb6118b610c2fc60178

António Nuno Monteiro pointed out:
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L2666

            (let [mchk  #?(:clj  (some-> (find-ns 'clojure.spec)
                                   (ns-resolve 'macroexpand-check))
                           :cljs (and ^::no-resolve cljs.spec
                                      ^::no-resolve cljs.spec/macroexpand-check))
Comment by Antonin Hildebrand [ 10/Oct/16 9:27 AM ]

I'm also seeing it: https://travis-ci.org/binaryage/dirac/builds/166433885#L815

Comment by António Nuno Monteiro [ 07/Nov/16 11:01 AM ]

Attached patch with fix and test.

Comment by David Nolen [ 07/Nov/16 2:39 PM ]

fixed https://github.com/clojure/clojurescript/commit/88ff3178509ffe93f2522eaeb6a8e2f63163605a





[CLJS-1842] Remove analyzer `:merge` hack for REPLs Created: 07/Nov/16  Updated: 07/Nov/16  Resolved: 07/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Task Priority: Major
Reporter: António Nuno Monteiro Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1842.patch    

 Description   

This is not needed anymore now that `require` et al. are a thing.



 Comments   
Comment by António Nuno Monteiro [ 07/Nov/16 12:52 PM ]

Attached patch.

Comment by David Nolen [ 07/Nov/16 2:36 PM ]

fixed https://github.com/clojure/clojurescript/commit/5aa574f4fac4066685e6a6929dd832b04ffd16e3





[CLJS-1768] cljs.spec perf tweaks Created: 31/Aug/16  Updated: 07/Nov/16  Resolved: 07/Nov/16

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: Next

Type: Task Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-1768.patch    

 Description   

Same as the following commits:

https://github.com/clojure/clojure/commit/de6a2b528a18bcb4768e82d0d707d2cab26268a6
https://github.com/clojure/clojure/commit/defa7b8ef268ea2b8772658ade2010ca5ad00dc4



 Comments   
Comment by António Nuno Monteiro [ 07/Nov/16 8:12 AM ]

Attached a patch with fix.

To make it easy to review, I've pushed a branch with the 4 separate (Clojure) commits that make up this patch here: https://github.com/anmonteiro/clojurescript/tree/spec-perf-tweaks

Comment by David Nolen [ 07/Nov/16 2:36 PM ]

fixed https://github.com/clojure/clojurescript/commit/de05b15568c848a1d4f80a44bdffd486abd05150





[CLJS-1622] `with-redefs` can cause `&` argument to be assigned incorrectly under advanced compilation Created: 12/Apr/16  Updated: 07/Nov/16  Resolved: 07/Nov/16

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

Type: Defect Priority: Minor
Reporter: Peter Jaros Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

Given the following:

(ns with-redefs-bug.core)

(enable-console-print!)

(defn a-function [arg-1 arg-2 & args]
  nil)

(with-redefs [a-function (fn [& args] args)]
  (prn (a-function :arg-1))
  (prn (a-function :arg-1 :arg-2))
  (prn (a-function :arg-1 :arg-2 :arg-3)))

Under :optimizations :none, this code correctly prints:

(:arg-1)
(:arg-1 :arg-2)
(:arg-1 :arg-2 :arg-3)

However, under :optimizations :advanced, this code prints:

(:arg-1)
(:arg-1 :arg-2)
:arg-1

That is, as long as the function is called with exactly or less than the number of non-variadic arguments in the original function bound to a-function, args is (correctly) bound to a seq of all the arguments, but if any more arguments are given, args is bound to the first argument.

Also, under either compilation, the following warning is generated:

WARNING: Wrong number of args (1) passed to with-redefs-bug.core/a-function at line 9

That surprises me, but since it happens under both methods, perhaps it's intentional.



 Comments   
Comment by Peter Jaros [ 12/Apr/16 4:21 PM ]

Reproduced on r1.8.40 and current master (29eb8e0).

Comment by Mike Fikes [ 12/Apr/16 8:24 PM ]

This is actually not specific to :optimizations :advanced, but to :static-fns true.

Comment by António Nuno Monteiro [ 05/Nov/16 9:22 AM ]

This seems to be the same case as CLJS-1623.

If we revise the failing example to include the `^:dynamic` metadata, it works as expected.

Comment by David Nolen [ 07/Nov/16 10:48 AM ]

This is not a bug.





[CLJS-1518] Case macro expansion evaluates expression twice Created: 21/Dec/15  Updated: 07/Nov/16

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