<< Back to previous view

[CLJS-1461] Convert analyzer to conform to tools.analyzer's spec Created: 28/Sep/15  Updated: 22/Jun/18

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

Type: Enhancement Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: Ambrose Bonnaire-Sergeant
Resolution: Unresolved Votes: 10
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/pull/7

Order of work:

  1. DONE Patch 1
    • :const
      • rename :constant op to :const
      • add :val entry
  2. Patch 2
    • :the-var
      • rename :var-special op to :the-var
    • :deftype
      • rename :deftype* op to :deftype
    • :defrecord
      • rename :defrecord* op to :defrecord
    • :with-meta
      • rename :meta op to :with-meta
  3. :def
    • add :ns entry
  4. :throw
    • rename :throw entry to :exception
  5. :try
    • rename :try entry to :body
  6. :letfn
    • rename :expr entry to :body
  7. :let/:loop
    • rename :expr entry to :body
  8. :quote
    • add :quote op
  9. :host-field/:host-method
    • split :dot op into :host-field/:host-method
  10. :invoke
    • rename :f to :fn
  11. :js-object/:js-array
    • split :js-value op into :js-object/:js-array
  1. :var/:binding/:local/:js-var
    • split :var op into :var/:binding/:local/:js-var
    • emit :local op if :js-shadowed-by-local
    • change :local to be #{:fn :letfn :let :arg ...}
  2. :fn-method
    • add :fn-method op to :methods of a :fn
    • :variadic -> :variadic?
    • :expr -> :body
    • add :fixed-arity
  3. :children
    • move to tools.analyzer :children format
      • :children are a sequence of keyword keys
      • ensure all sequence children are vectors
    • replace :children calls with a compatible function from AST -> children
  4. Unit tests
    • add them all at the end
  5. AST format documentation
    • modify from tools.analyzer's

Extra stuff:

  • argument validation in 'var parsing
  • :max-fixed-arity -> :fixed-arity
  • :case node overhaul
    • which format do we follow?
    • TAJ vs TAJS


 Comments   
Comment by Ambrose Bonnaire-Sergeant [ 13/Sep/17 6:56 AM ]

In the body of this issue I have proposed a sequence of potential patches such that each patch will be easily screenable.

Can I have some feedback on this? Should some of these steps be combined/split?





[CLJS-2787] Record comparison is broken when instance is constructed from another record instance via map factory Created: 21/Jun/18  Updated: 22/Jun/18  Resolved: 22/Jun/18

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

Type: Defect Priority: Major
Reporter: Yuri Govorushchenko Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

CLJS



 Description   

Steps:

(defrecord A [])
(def x (map->A {1 2}))
(def y (map->A x))
(= x y)

Actual: false.

Expected: true (as in Clojure).



 Comments   
Comment by David Nolen [ 22/Jun/18 3:49 PM ]

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





[CLJS-2589] allow '/' as a protocol method name in cljs Created: 01/Mar/18  Updated: 22/Jun/18

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

Type: Defect Priority: Minor
Reporter: Henry Widd Assignee: Henry Widd
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS_2589_allow___as_a_protocol_method_name_in_cljs.patch    

 Description   

Although the following compiles in cljs (and so 'cljs.div//' exists), an error is thrown on calling the function. It works as expected in Clojure.

I will try to make a patch for this and attach when ready

(ns cljs.div
(:refer-clojure :exclude [/]))

(defprotocol p
(/ [_]))

(extend-type
#?(:clj String :cljs string)
p
(/ [_] "result"))

; this throws
(/ "")



 Comments   
Comment by Henry Widd [ 20/Mar/18 4:24 AM ]

analyzing a form such as:

'(defprotocol P (/ [_]))

and inspecting the ast as follows: (-> x :children (nth 2) :form),

the form contains
(cljs.core/nil? (. _ -cljs$user$P$/$arity$1))))

The property 'cljs$user$P$/$arity$1' is emitted with '/' being read as if it were an ns/fn marker. So you get javascript like _._cljs$user$P$.$arity$1() instead of _._cljs$user$P$/$arity$1

The method name '/' is changed to _SLASH_ during emit. However, perhaps emitting would be too late to change the '/' in the cljs$user$P$/$arity$1 property, so analysis would be a better place to change the name of this property?

Comment by Henry Widd [ 28/Mar/18 2:52 AM ]

attached is an attempt at a fix. tests pass and the problem i had has gone away but it's quite possible it's not totally correct.

any feedback v. welcome

Comment by David Nolen [ 22/Jun/18 3:47 PM ]

Please construct a patch using the guidelines - thanks https://clojurescript.org/community/patches





[CLJS-2260] Convert :constant AST node to tools.analyzer format Created: 18/Jul/17  Updated: 22/Jun/18  Resolved: 22/Jun/18

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

Type: Enhancement Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: David Nolen
Resolution: Completed Votes: 2
Labels: None

Attachments: Text File CLJS-2260.patch     Text File const-ast-2.patch     Text File const-ast.patch    
Patch: Code
Approval: Accepted

 Description   

Part of https://dev.clojure.org/jira/browse/CLJS-1461

Work on :const node:

  • rename :constant op to :const
  • add :val entry


 Comments   
Comment by David Nolen [ 15/Sep/17 3:24 PM ]

This patch needs a rebase.

Comment by Amanda Walker [ 23/Sep/17 8:13 PM ]

Here is the rebased patch.

Comment by Ambrose Bonnaire-Sergeant [ 22/Jun/18 2:06 PM ]

Attached rebased patch as `CLJS-2260.patch`.

Comment by David Nolen [ 22/Jun/18 3:27 PM ]

fixed https://github.com/clojure/clojurescript/commit/3620434c8ae812d2127f4b162d82e2c99cd104aa





[CLJS-2786] implement cljs.core/extend, same as clojure.core/extend Created: 21/Jun/18  Updated: 21/Jun/18

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

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


 Description   

I'll try to create a patch.



 Comments   
Comment by David Nolen [ 21/Jun/18 2:50 PM ]

Whatever we come up with needs to be compatible with advanced compilation. Perhaps goog.reflect can help here? https://github.com/google/closure-library/blob/master/closure/goog/reflect/reflect.js





[CLJS-2466] Faster reduce for lazy-seqs Created: 12/Jan/18  Updated: 19/Jun/18

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

Type: Enhancement Priority: Minor
Reporter: A. R Assignee: David Nolen
Resolution: Unresolved Votes: 5
Labels: None

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

 Description   

Lazy seqs that are built from vectors/chunked-seqs can sometimes take a slow first/next reduce.

Observation:

(def xs (vec (range 3000000)))

(time (reduce max xs)) ;; #1: 130ms, (reference)
(time (reduce max (lazy-cat xs))) ;; #2: 130ms, just as fast
(time (reduce max 0 (lazy-cat xs))) ;; #3: 500ms, 4x slower!!

;; Double them with concat and they're not 2x slower but 10x slower:
(time (reduce max (lazy-cat xs xs))) ;; #4: 1200ms
(time (reduce max 0 (lazy-cat xs xs))) ;; #5: 1200ms

Explanation for #3: The problem is that seq-reduce when called without init will properly call reduce again and take a fast path. With init given it won't ever escape to a faster reduce but will stick to first/next.

Note: In Clojure they scale "properly" (first 3 are ~45ms, last 2 are ~110ms).

The reason is that Clojure properly escapes to a fast path:

https://github.com/clojure/clojure/blob/2b242f943b9a74e753b7ee1b951a8699966ea560/src/clj/clojure/core/protocols.clj#L131-L143

This is an RFC, since I'm not 100% certain about the implemenation. Need to be careful to not blow the stack here...

Questions:
1. Should ChunkedCons implement IReduce? I think so.



 Comments   
Comment by A. R [ 12/Jan/18 1:59 AM ]

Timings with advanced compilation:

CHROME:
"OLD"
#1: "Elapsed time: 21.870000 msecs"
#2: "Elapsed time: 25.485000 msecs"
#3: "Elapsed time: 134.900000 msecs"
#4: "Elapsed time: 317.155000 msecs"
#5: "Elapsed time: 313.225000 msecs"
"NEW"
#1: "Elapsed time: 23.290000 msecs"
#2: "Elapsed time: 19.445000 msecs"
#3: "Elapsed time: 20.075000 msecs"
#4: "Elapsed time: 102.895000 msecs"
#5: "Elapsed time: 100.430000 msecs"
"OLD"
#1: "Elapsed time: 19.585000 msecs"
#2: "Elapsed time: 19.475000 msecs"
#3: "Elapsed time: 87.805000 msecs"
#4: "Elapsed time: 303.340000 msecs"
#5: "Elapsed time: 291.680000 msecs"
"NEW"
#1: "Elapsed time: 20.760000 msecs"
#2: "Elapsed time: 19.690000 msecs"
#3: "Elapsed time: 18.960000 msecs"
#4: "Elapsed time: 101.385000 msecs"
#5: "Elapsed time: 101.290000 msecs"

FIREFOX:

"OLD"
#1: "Elapsed time: 7.880000 msecs"
#2: "Elapsed time: 7.820000 msecs"
#3: "Elapsed time: 69.460000 msecs"
#4: "Elapsed time: 197.800000 msecs"
#5: "Elapsed time: 209.300000 msecs"
"NEW"
#1: "Elapsed time: 7.380000 msecs"
#2: "Elapsed time: 7.360000 msecs"
#3: "Elapsed time: 8.100000 msecs"
#4: "Elapsed time: 110.640000 msecs"
#5: "Elapsed time: 89.960000 msecs"
"OLD"
#1: "Elapsed time: 6.520000 msecs"
#2: "Elapsed time: 7.360000 msecs"
#3: "Elapsed time: 106.920000 msecs"
#4: "Elapsed time: 252.300000 msecs"
#5: "Elapsed time: 249.800000 msecs"
"NEW"
#1: "Elapsed time: 7.360000 msecs"
#2: "Elapsed time: 6.940000 msecs"
#3: "Elapsed time: 6.880000 msecs"
#4: "Elapsed time: 99.380000 msecs"
#5: "Elapsed time: 53.220000 msecs"
Comment by A. R [ 12/Jan/18 2:14 AM ]

Impact on truly (unchunked) lazy-seqs is neglibile (hard to measure due to garbage collection causing a lot of variance).

Comment by A. R [ 12/Jan/18 10:22 AM ]

New ticket for reduce for ChunkedCons: CLJS-2468

Comment by A. R [ 13/Jan/18 7:00 AM ]

Depends on CLJS-2469 for tests to pass. Patch is attached.

Comment by Thomas Mulvaney [ 18/Jun/18 12:16 PM ]

ChunkedSeq's already implements an efficient reduce stategy. I believe the issue is that LazySeq which is just a container that may have a different type of seq inside, is always calling `seq-reduce` on that inner sequence. Sometimes, such as in the case of ChunkedSeq, the inner sequence actually knows how to reduce itself best.

So I think the solution is as simple as changing the body of LazySeq.IReduce.-reduce from: (seq-reduce f init coll) to (reduce f init (seq coll). The key here, is calling seq pulls out the inner seq if there is one, and then reduce will call the best pathway for it.

Hope this helps.

Comment by A. R [ 18/Jun/18 1:08 PM ]

I don't think that's a good idea. You can easily blow the stack with that approach. Though, I haven't tried it.

Comment by Thomas Mulvaney [ 19/Jun/18 4:43 AM ]

One thing worth considering, the patch improves a particular case, ChunkedSeqs. seqs of hash-maps, IndexedSeqs, Ranges, are not handled. Dispatching, to reduce would fix this. You may have a point about blowing the stack, I haven't experimented though.

For example, (reduce + (range 10000)) is much faster than (reduce + (lazy-cat (range 10000)), but making LazySeq's reduce call reduce on the inner collection should fix this issue.

Comment by A. R [ 19/Jun/18 1:22 PM ]

Thomas, happy to bounce ideas back and forth. Feel free to compare your ideas to my patch with perf measures. The problem with calling reduce on the inner fn is the stack and also the non-preserving reduce. And wrapping the reducing function is pretty expensive. I tried that and it's much slower. IIRC that's why I did it that way. But again, need to be very careful not to blow the stack. That'd be a huge problem for users.





[CLJS-2785] npm-deps throws errors when using a dependency with es6 modules Created: 19/Jun/18  Updated: 19/Jun/18

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

Type: Defect Priority: Major
Reporter: Moritz Ulrich Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Using npm-deps to specify a dependency on a library with es6 modules causes errors in Google Closure, making the dependency unusable.

Background

rc-time-picker comes as a set of es6 modules in the es/ subfolder as well as "traditional" module.exports in the lib/ subdirectory. The package.json specifies both as module and main respectively (see https://github.com/react-component/time-picker/blob/master/package.json).

Using this in a clojurescript build with npm-deps like the following makes google closure pick the es6 part and later complain about the file mixing goog.provide and es6 modules:

(require '[cljs.build.api :as b])

(b/build ["src/"]
         {:main 'my.app
          :output-to "js/app.js"
          :optimizations :simple
          :npm-deps {"react"          "16.2.0",
                     "react-dom"      "16.2.0",
                     "rc-time-picker" "^3.3.1",}
          :install-deps true})

A simple app.cljs requiring "rc-time-picker" :as ... causes the following errors during compilation:

WARNING: WARNING - File cannot be a combination of goog.provide, goog.module, and/or ES6 module: .../out/node_modules/rc-time-picker/es/Combobox.js
...
ERROR: JSC_LANGUAGE_FEATURE. This language feature is only supported for ECMASCRIPT6 mode or better: modules. at ...out/node_modules/rc-time-picker/es/TimePicker.js line 12 :66
...

Specifying :language-in and :language-out doesn't help.

The error messages are caused by the Clojurescript code which copies the code from node_modules/rc-time-picker/es/ to out/node_modules/rc-time-picker and where it adds various goog.provide statements to the top of the file, while the end of the file is a export default ... statement.






[CLJS-2758] Improving tracability of cljs.spec.test instrumented function call conform errors Created: 24/May/18  Updated: 19/Jun/18

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

Type: Enhancement Priority: Major
Reporter: Christian Johansen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, enhancement, spec

Attachments: Text File 0001-Change-target-to-default-which-indicates-a-browser.patch     Text File 0002-Use-location.hostname-for-port-less-hostname.patch     Text File 0003-Infer-UA-product-for-error-parsing-from-error-stack-.patch     Text File 0004-Correct-namespace-for-locating-caller-in-spec.test.patch    
Patch: Code

 Description   

Context: Use `cljs.spec.test.alpha/instrument` to instrument `fdef`-ed functions. Call one of said functions with data that fails the argument spec. The thrown exception currently does not provide a lot of context:

1. The exception message contains "missing filename" and "missing line number" - ideally those should contain the file and line number of the offending call
2. The exception data is coded to include information about the caller, but the current implementation always yields `nil` here.

The result is that failure to conform to an fdef argument spec leaves no trace back to the call - it only tells you which function's spec was not satiesfied.

I've started to investigate, and found a few glitches, but I do not have a complete suggestion. I'm offering my patches so far, hoping to get some input on whether or not it would be desirable for me to continue investigating.

Here's what I found so far:

1. `target` was assumed to be `"browser"`, while it is documented to be `"default"` in browsers. Fixed in first patch
2. When attempting to parse the stack trace to find the caller, `host` included the port number. Adressed in the second patch
3. When attempting to parse the stack trace, `goog.userAgent.product` is used to determine the browser, but it is not reliable - for example, `product/IPHONE` is true when Chrome is in responsive design mode. This is both incorrect, and helpeless in the case of `cljs.spec.test.alpha`, which does not recognize iphones at all. Because the user agent is only used to parse stack traces, I fixed this by inferring the user agent from the stack trace instead.
4. The `find-caller` function used the wrong package name to find the `spec_checking_fn`. Additionally, it hard-coded the dots in the package name, while some browsers use `$`. I fixed this in the forth patch. I also moved creating the error outside of the `conform!` anonymous function, as placing it here removes `spec-checking-fn` from the stack trace.

With these patches, the caller is set reliably, although it doesn't seem to reflect the originating call-site. Also, the thrown exception still lacks file name and line number. I'd be happy to continue investigating, and add some tests if you are interested in eventually accepting these patches.

As a side-note: It seems to me that the function that infers user agent from stack trace more appropriately belongs in stacktrace.cljs, and I feel strongly that this should be the default behavior when no `user-agent-product` is provided (instead of the current: returning the stack trace string unmodified). I'll be happy to fix this as well, and add some tests, if the interest is there. Note that the current approach allows Safari to go down the Firefox route, which works like a charm.

Lastly: sorry if I put too many things in one place, I'll be happy to split up as instructed.



 Comments   
Comment by David Nolen [ 15/Jun/18 3:52 PM ]

Thanks! Have you submitted a CA?

Comment by Christian Johansen [ 19/Jun/18 4:21 AM ]

I sure have





[CLJS-2750] Tag coll as not-native in ci-reduce Created: 09/May/18  Updated: 18/Jun/18

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

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

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

 Description   

ci-reduce is a private function in cljs.core for reducing collections which are IIndexed and ICounted. It's first argument is always a collection which implements these protocols, as such, letting the compiler know that the collection is ^not-native allows for direct calls to the IIndexed.nth method of the collection.

In particular, this improved the performance of reducing over Range types using the 2-arity form of reduce, i.e., no init form, but also reducing of the various map-entries MapEntry, RedNode and BlackNode.

Finally, the 4-arity version of ci-reduce, where the 4th arg is an index to start at, was deleted because it is no longer called anywhere.

Output of some naive microbenchmarks performed with simple-benchamrk are:

V8 (6.8.0)

Benchmark Before (msecs) After (msecs)
[r (range 10000)], (reduce + r), 1000 runs 249 242
[m (apply hash-map (range 100000))], (transduce cat + 0 m), 1000 runs 18907 11744
[m (apply sorted-map (range 100000))], (transduce cat + 0 m), 1000 runs 32331 20084

JavascriptCore

Benchmark Before (msecs) After (msecs)
[r (range 10000)], (reduce + r), 1000 runs 234 40
[m (apply hash-map (range 100000))], (transduce cat + 0 m), 1000 runs 12252 8962
[m (apply sorted-map (range 100000))], (transduce cat + 0 m), 1000 runs 16084 13233


 Comments   
Comment by Thomas Mulvaney [ 09/May/18 4:00 PM ]

I did not notice that there are a couple of existing benchmarks for ci-reduce already in benchmark_runner.cljs. These benchmarks call ci-reduce directly, even though its private, and even though the collection being reduced, an IndexedSeq, uses array-reduce internally when reduced via the usual reduce function. Regardless, here are the outputs:

V8

Benchmark Before (msecs) After (msecs)
[coll (seq arr)], (ci-reduce coll + 0), 1 runs 33 23
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs 38 30

JavascriptCore

Benchmark Before (msecs) After (msecs)
[coll (seq arr)], (ci-reduce coll + 0), 1 runs 25 15
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs 25 15
Comment by David Nolen [ 15/Jun/18 4:34 PM ]

This needs to handle the case where someone has extended native types though right?

Comment by Thomas Mulvaney [ 18/Jun/18 4:33 AM ]

I believe this is okay.

The function reduce itself does not actually call ci-reduce anymore (as of 7e7f3a76eefd621165259c0f24d6507318dca029). I'm guessing this was the source of your concern? ci-reduce is only called from within the IReduce.-reduce methods of various clojure data types now, so I can't see an extended native type ever ending up as an argument.

I may have misunderstood something though.





[CLJS-2757] Failure to load is-plain-object transitive npm dep Created: 21/May/18  Updated: 18/Jun/18

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

Type: Defect Priority: Major
Reporter: Mike Fikes Assignee: Mike Fikes
Resolution: Unresolved Votes: 5
Labels: npm-deps
Environment:

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   

The slate npm dep depends on is-plain-object but it can't be loaded. Start up a REPL with:

clojure -m cljs.main -co '{:npm-deps {"react" "15.5.4" "react-dom" "15.5.4" "slate" "0.33.6" "immutable" "3.8.2"} :install-deps true :repl-verbose true}' -d out -r

(Note, that in the above we are going with the default browser REPL; the problem doesn't occur if you specify -re node.)

Then, after the REPL is up and running:

cljs.user=> (require 'slate)
load-namespace module$private$tmp$test-me$node-modules$slate$lib$slate-es , compiled: ((module$private$tmp$test-me$node-modules$slate$lib$slate-es))
goog.addDependency("../node_modules/slate/lib/slate.es.js", ['module$private$tmp$test_me$node_modules$slate$lib$slate_es'], ['module$is_plain_object', 'module$immutable', 'module$slate_dev_logger', 'module$direction', 'module$esrever', 'module$debug', 'module$lodash$isEqual', 'module$lodash$mergeWith', 'module$slate_schema_violations', 'module$lodash$pick', 'module$lodash$omit', 'module$is_empty']);

goog.require('module$private$tmp$test_me$node_modules$slate$lib$slate_es');
null;

"Error evaluating:" (require (quote slate)) :as "goog.require('module$private$tmp$test_me$node_modules$slate$lib$slate_es');\nnull;\n"
Error: Undefined nameToPath for module$is_plain_object
	 (out/goog/base.js:1357:26)
	 (out/goog/base.js:1369:14)
	 (out/goog/base.js:706:27)
	 require (out/clojure/browser/repl.cljs:340:25)

Note that it can't load module$is_plain_object, which is specified via

goog.require("module$is_plain_object");

inside of out/node_modules/slate/lib/slate.es.js.

But, you can load that namespace directly:

cljs.user=> (require 'is-plain-object)
load-namespace module$private$tmp$test-me$node-modules$is-plain-object$index , compiled: ([module$private$tmp$test-me$node-modules$isobject$index] (module$private$tmp$test-me$node-modules$is-plain-object$index))
goog.addDependency("../node_modules/isobject/index.js", ['module$private$tmp$test_me$node_modules$isobject$index'], []);
goog.addDependency("../node_modules/is-plain-object/index.js", ['module$private$tmp$test_me$node_modules$is_plain_object$index'], ['module$private$tmp$test_me$node_modules$isobject$index']);

goog.require('module$private$tmp$test_me$node_modules$is_plain_object$index');
null;

This appears to be the result of Closure failing to find the correct paths to the modules and simply emitting module$<symbol> instead of module$<path> for the goog.require.



 Comments   
Comment by Dieter Komendera [ 18/Jun/18 4:06 AM ]

Current master produces a different problem.

These errors are now logged:

Can't find variable: module
undefined is not an object (evaluating 'module$Users$kommen$work$clojurescript$node_modules$slate$node_modules$debug$src$debug["default"]')
TypeError: undefined is not a constructor (evaluating 'new module$Users$kommen$work$clojurescript$node_modules$immutable$dist$immutable.Map')

Juho suggested the original issue actually might have been a duplicate of CLJS-2746.

Comment by Mike Fikes [ 18/Jun/18 6:24 AM ]

Yes, CLJS-2746 is definitely in the area. Perhaps the issue described in this ticket is now resolved and we are onto completely different issues.





[CLJS-2770] Problem with namespaces starting with com in Rhino Created: 09/Jun/18  Updated: 17/Jun/18

Status: Reopened
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: None
Environment:

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}


Approval: Screened

 Description   
$ clj -m cljs.main -re rhino -r
ClojureScript 1.10.238
cljs.user=> (ns com.foo)

com.foo=> (def x 3)
#'com.foo/x
com.foo=> x
org.mozilla.javascript.EcmaError: TypeError: Cannot call property cljs$lang$ctorPrWriter in object [JavaPackage com.foo.x]. It is not a function, it is "object". (/var/folders/gx/nymj3l7x4zq3gxb97v2zwzb40000gn/T/out314052489996668423318817887553502/goog/../cljs/core.js#32857)
	 cljs$core$pr_writer_impl (cljs/core.cljs:9919:9)
	 cljs.core/pr-writer (cljs/core.cljs:10003:5)
	 cljs.core/pr-seq-writer (cljs/core.cljs:10006:4)
	 cljs$core$pr_sb_with_opts (cljs/core.cljs:10014:6)
	 cljs$core$pr_str_with_opts (cljs/core.cljs:10024:5)
	 (cljs/core.cljs:10052:3)
	 cljs$core$pr_str (cljs/core.cljs:10049:1)
	 (<NO_SOURCE_FILE> <cljs repl>:1:0)


 Comments   
Comment by David Nolen [ 15/Jun/18 3:48 PM ]

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

Comment by David Nolen [ 17/Jun/18 9:04 AM ]

See CLJS-2784. Reverting and lowering the priority on this one.

Comment by Thomas Heller [ 17/Jun/18 10:29 AM ]

Given that the error message contains JavaPackage com.foo.x is it possible that this affects anything that has a Java class loaded? Given that Java uses TLDs commonly how about org?





[CLJS-2784] Namespace never provided error Created: 16/Jun/18  Updated: 17/Jun/18  Resolved: 17/Jun/18

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

Type: Defect Priority: Major
Reporter: Gal Dolber Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: regression
Environment:

{:deps {org.clojure/clojurescript {:git/url "https://github.com/clojure/clojurescript"
:sha "ec1e416bccf7ad2d63d8e97a156dec989fa1a9d7"}
com.cognitect/transit-cljs {:mvn/version "0.8.256"}}}



 Description   
src/foo/core.cljs
(ns foo.core
 (:require cognitect.transit))
$ clj -m cljs.main -O advanced -c foo.core
Jun 17, 2018 9:09:56 AM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: /Users/mfikes/Desktop/cljs-2784/out/cognitect/transit.js:5: ERROR - required "com$.cognitect.transit" namespace never provided
goog.require('com$.cognitect.transit');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Jun 17, 2018 9:09:56 AM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: /Users/mfikes/Desktop/cljs-2784/out/cognitect/transit.js:6: ERROR - required "com$.cognitect.transit.types" namespace never provided
goog.require('com$.cognitect.transit.types');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Jun 17, 2018 9:09:56 AM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: /Users/mfikes/Desktop/cljs-2784/out/cognitect/transit.js:7: ERROR - required "com$.cognitect.transit.eq" namespace never provided
goog.require('com$.cognitect.transit.eq');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

Reverting this commit seems to fix the issue:
https://github.com/clojure/clojurescript/commit/ec1e416bccf7ad2d63d8e97a156dec989fa1a9d7

The root cause is that, even though the intent is to munge com to com$ universally (including munging the goog.provide statements emitted for ClojureScript namespaces that start with com), it doesn't munge non-compiled goog.provide statements that are explicitly authored by hand: https://github.com/cognitect/transit-js/blob/b3cf3d60da339b73d269f14713cced33332d43a7/src/com/cognitect/transit.js#L17



 Comments   
Comment by David Nolen [ 17/Jun/18 9:03 AM ]

Hrm yeah, I'm OK on giving up on Rhino for this particular issue for now. We should reopen and lower the priority on CLJS-2770.

Comment by David Nolen [ 17/Jun/18 9:06 AM ]

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





[CLJS-2780] Async tests prematurely terminate in Node Created: 15/Jun/18  Updated: 16/Jun/18  Resolved: 16/Jun/18

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

Type: Defect Priority: Major
Reporter: Mike Fikes Assignee: Mike Fikes
Resolution: Completed Votes: 0
Labels: regression
Environment:

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}


Attachments: Text File CLJS-2780.patch    
Patch: Code and Test
Approval: Accepted

 Description   

If you run cljs.test tests in Node where any are async, things may not terminate properly.

In this example, the js/setTimeout keeps Node alive, but something may happen near the very end of execution that causes failure.

src/foo/runner.cljs
(ns foo.runner
  (:require
   [clojure.test :refer [run-tests]]
   [foo.core-test]))

(defn -main [& args]
  (run-tests 'foo.core-test))
src/foo/core_test.cljs
(ns foo.core-test
  (:require
   [clojure.test :refer [deftest async is]]))

(deftest bar
  (async done
    (js/setTimeout
      #(do
         (is (= 1 1))
         (done))
      1000)))

Here is what execution with Node looks like:

$ clj -m cljs.main -re node -m foo.runner

Testing foo.core-test

Compare this with Nashorn:

$ clj -m cljs.main -re nashorn -m foo.runner

Testing foo.core-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Likewise, this works properly with Planck:

$ plk -m foo.runner

Testing foo.core-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

and Lumo:

$ lumo -c src -m foo.runner

Testing foo.core-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

The only reason for illustrating Planck and Lumo (which is based on Node) is to suggest that some reasonable small tweak that would make this work in Node is within reach.



 Comments   
Comment by Mike Fikes [ 16/Jun/18 2:33 PM ]

This is a regression that occurred during the betas leading up to the 1.10.238 release.

This worked properly with the 1.10.191 beta release

{:deps {org.clojure/clojurescript {:mvn/version "1.10.191"}}}

and so did this use case from CLJS-2574:

clj -m cljs.main -re node -e '(js/setTimeout #(prn :hi) 1000)' -e ':goodbye'

Git bisect result:

84004ff7d90d48a730b2e1e8ebc2c421830462f7 is the first bad commit
commit 84004ff7d90d48a730b2e1e8ebc2c421830462f7
Author: David Nolen <david.nolen@gmail.com>
Date:   Mon Mar 19 12:21:33 2018 +0100

    refactor so that printing and evaluation result has a deterministic
    order at the REPL.

:040000 040000 442862c8f0e21e316b21567e697f7bca26e8b19d 64813d98c34da80a5e527745ed259b169594b729 M	src
Comment by Mike Fikes [ 16/Jun/18 4:33 PM ]

See commit comment for explanation of patch.

Comment by Mike Fikes [ 16/Jun/18 10:01 PM ]

Fixed https://github.com/clojure/clojurescript/commit/5dc641ed1bf5ea642a9cb00f0fc770eb479c23bb





[CLJS-2783] with-out-str conflicts with :infer-externs Created: 16/Jun/18  Updated: 16/Jun/18  Resolved: 16/Jun/18

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

Type: Defect Priority: Minor
Reporter: Gal Dolber Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: infer-externs
Environment:

macOS


Patch: Code
Approval: Accepted

 Description   
(println (with-out-str (println "bug")))

Produces the following warning by producing a wrong inferred-externs.js:

WARNING: target/node/dev/inferred_externs.js:3: WARNING - name goog is not defined in the externs.
goog.string;
^^^^

Jun 16, 2018 2:55:45 PM com.google.javascript.jscomp.LoggerErrorManager println
WARNING: target/node/dev/inferred_externs.js:4: WARNING - name goog is not defined in the externs.
goog.string.StringBuffer;
^^^^

Jun 16, 2018 2:55:45 PM com.google.javascript.jscomp.LoggerErrorManager println
WARNING: target/node/dev/inferred_externs.js:5: WARNING - name goog is not defined in the externs.
goog.string.StringBuffer.prototype.append;
^^^^

The problem seems to go away when removing the "js/" below on "js/goog.string.StringBuffer.":

(core/defmacro with-out-str
  "Evaluates exprs in a context in which *print-fn* is bound to .append
  on a fresh StringBuffer.  Returns the string created by any nested
  printing calls."
  [& body]
  `(let [sb# (js/goog.string.StringBuffer.)]
     (binding [cljs.core/*print-newline* true
               cljs.core/*print-fn* (fn [x#] (.append sb# x#))]
       ~@body)
     (cljs.core/str sb#)))


 Comments   
Comment by David Nolen [ 16/Jun/18 9:06 PM ]

fixed https://github.com/clojure/clojurescript/commit/6048bc95001e1d5f1c996c5cda187cdfc0193bc8





[CLJS-2746] Missing/Incorrect provides for node module required from ES6 module Created: 01/May/18  Updated: 16/Jun/18  Resolved: 15/Jun/18

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

Type: Defect Priority: Major
Reporter: Corin Lawson Assignee: David Nolen
Resolution: Completed Votes: 1
Labels: foreign-libs, modules, npm-deps
Environment:

Linux 4.16.2 #23 SMP Mon Apr 30 11:01:40 AEST 2018 x86_64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz GenuineIntel GNU/Linux


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

 Description   

Affects: 1.10.271 with CLJS-2402.patch

I have a minimal repro repo here: https://github.com/au-phiware/cljs-in-js-in-cljs

Description of problem

The compiler appears to know node modules that are required from foreign libs by two different names, but the cljs_deps.js file only uses one of them. In the repro case below, unique-random is referenced as both module$unique_random and module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index in the compiled output of the foreign lib (}target/main.out/es6/hello.js}), but {{cljs_deps.js only specifies module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index as its provides.

Steps to reproduce the problem

Consider the following source files:

src/hello/core.cljs
(ns hello.core (:require [unique-random]
                         [hello :refer [greet]]))

(greet "test")
es6/hello.js
import random from "unique-random";
export var greet = function(m) {
    document.write("Hello, " + m + random(1, 100)());
};
build.clj
(require 'cljs.build.api)

(cljs.build.api/build
  "src"
  {:main 'hello.core
   :output-to "target/main.js"
   :output-dir "target/main.out"
   :asset-path "main.out"
   :foreign-libs [{:file "es6"
                   :module-type :es6}]
   :install-deps true
   :npm-deps {:unique-random "latest"}})

Execute cljs:

java -cp cljs.jar:src clojure.main build.clj

Expected outcome

cljs should produce nothing to the standard output, exit cleanly and write the following files (approximately).

target/main.js
var CLOSURE_UNCOMPILED_DEFINES = {};
var CLOSURE_NO_DEPS = true;
if(typeof goog == "undefined") document.write('<script src="main.out/goog/base.js"></script>');
document.write('<script src="main.out/goog/deps.js"></script>');
document.write('<script src="main.out/cljs_deps.js"></script>');
document.write('<script>if (typeof goog == "undefined") console.warn("ClojureScript could not load :main, did you forget to specify :asset-path?");</script>');
document.write('<script>goog.require("process.env");</script>');
document.write('<script>goog.require("hello.core");</script>');
target/main.out/cljs_deps.js
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../node_modules/unique-random/index.js", ['module$unique_random', 'module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index'], []);
goog.addDependency("../es6/hello.js", ['module$usr$src$cljs_in_js_in_cljs$es6$hello'], ['module$unique_random']);
goog.addDependency("../hello/core.js", ['hello.core'], ['cljs.core', 'module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index', 'module$usr$src$cljs_in_js_in_cljs$es6$hello']);
target/main.out/es6/hello.js
goog.provide("module$usr$src$cljs_in_js_in_cljs$es6$hello");
goog.require("module$unique_random");
var greet$$module$usr$src$cljs_in_js_in_cljs$es6$hello=function(m){document.write("Hello, "+m+module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index["default"](1,100)())};var module$usr$src$cljs_in_js_in_cljs$es6$hello={};module$usr$src$cljs_in_js_in_cljs$es6$hello.greet=greet$$module$usr$src$cljs_in_js_in_cljs$es6$hello
target/main.out/hello/core.js
// Compiled by ClojureScript 1.10.272 {}
goog.provide('hello.core');
goog.require('cljs.core');
goog.require('module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index');
goog.require('module$usr$src$cljs_in_js_in_cljs$es6$hello');
module$usr$src$cljs_in_js_in_cljs$es6$hello.greet("test");

Caveat

The expected outcome was derived from the actual outcome with the minimal set of changes required to produce the desired outcome (i.e. working in the browser without error).

Alternatively, all references to module$unique_random could be replaced with module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index, for the same desired outcome.

Actual outcome

The cljs_deps.js file is missing the module$unique_random provides name for the node module.

target/main.out/cljs_deps.js
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../node_modules/unique-random/index.js", ['module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index'], []);
goog.addDependency("../es6/hello.js", ['module$usr$src$cljs_in_js_in_cljs$es6$hello'], ['module$unique_random']);
goog.addDependency("../hello/core.js", ['hello.core'], ['cljs.core', 'module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index', 'module$usr$src$cljs_in_js_in_cljs$es6$hello']);

The following is the diff output for clarity.

diff --git a/target/main.out/cljs_deps.js b/target/main.out/cljs_deps.js
index dd4df1f..de77e67 100644
--- a/target/main.out/cljs_deps.js
+++ b/target/main.out/cljs_deps.js
@@ -1,6 +1,6 @@
 goog.addDependency("base.js", ['goog'], []);
 goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
 goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
-goog.addDependency("../node_modules/unique-random/index.js", ['module$unique_random', 'module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index'], []);
+goog.addDependency("../node_modules/unique-random/index.js", ['module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index'], []);
 goog.addDependency("../es6/hello.js", ['module$usr$src$cljs_in_js_in_cljs$es6$hello'], ['module$unique_random']);
 goog.addDependency("../hello/core.js", ['hello.core'], ['cljs.core', 'module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index', 'module$usr$src$cljs_in_js_in_cljs$es6$hello'])

Furthermore, if optimisations is turned on (e.g. :optimizations :simple) the following error is observed from cljs.

stderr
May 01, 2018 5:50:49 PM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: /usr/src/cljs-in-js-in-cljs/target/main.out/es6/hello.js:2: ERROR - required "module$unique_random" namespace never provided
goog.require("module$unique_random");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

May 01, 2018 5:50:49 PM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 1 error(s), 0 warning(s)
ERROR: JSC_MISSING_PROVIDE_ERROR. required "module$unique_random" namespace never provided at /usr/src/cljs-in-js-in-cljs/target/main.out/es6/hello.js line 2 : 0
Exception in thread "main" java.lang.Exception: Closure compilation failed, compiling:(/usr/src/cljs-in-js-in-cljs/build.clj:3:1)
	at clojure.lang.Compiler.load(Compiler.java:7526)
	at clojure.lang.Compiler.loadFile(Compiler.java:7452)
	at clojure.main$load_script.invokeStatic(main.clj:278)
	at clojure.main$script_opt.invokeStatic(main.clj:338)
	at clojure.main$script_opt.invoke(main.clj:333)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
Caused by: java.lang.Exception: Closure compilation failed
	at cljs.closure$report_failure.invokeStatic(closure.clj:389)
	at cljs.closure$optimize.invokeStatic(closure.clj:1422)
	at cljs.closure$optimize.doInvoke(closure.clj:1382)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at cljs.closure$build.invokeStatic(closure.clj:2866)
	at cljs.build.api$build.invokeStatic(api.clj:207)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljs.build.api$build.invokeStatic(api.clj:195)
	at cljs.build.api$build.invoke(api.clj:189)
	at user$eval34.invokeStatic(build.clj:3)
	at user$eval34.invoke(build.clj:3)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	... 9 more


 Comments   
Comment by Corin Lawson [ 03/May/18 8:59 AM ]

I found some time to perform a git bisect and the module$unique_random name appears at v1.9.1033 (72e2ab6e) "CLJS-2389: Update Closure-compiler".

Comment by Corin Lawson [ 09/May/18 12:18 PM ]

I have found that ModuleNames/fileToModuleName produces module$usr$src$cljs_in_js_in_cljs$node_modules$unique_random$index for node_modules/unique-random/index.js and .getRequires produces {{#object[com.google.common.collect.RegularImmutableList [module$unique_random]]}} for es6/hello.js.

I found the location where the goog.provide statements are being written. Ensuring that a goog.provide statement is written for each name that the module provide resolves this problem, see attached patch.

Comment by David Nolen [ 15/Jun/18 4:18 PM ]

fixed https://github.com/clojure/clojurescript/commit/6950aff480174a25a77c2308aa87a099a774a6e8

Comment by Juho Teperi [ 16/Jun/18 2:37 PM ]

Good catch. I didn't remember that we add :provides lists to npm foreign-libs which is why I didn't think about this when I wrote the problematic code.





[CLJS-2782] lein test fails if directory has hyphens Created: 16/Jun/18  Updated: 16/Jun/18

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

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

Master as of https://github.com/clojure/clojurescript/commit/7528dc79fea372fafa365ee80e4568a3af5f1526



 Description   

Create a directory with hyphens in its name, and then clone clojurescript into it and run lein test.

lein test :only cljs.module-processing-tests/commonjs-module-processing-preprocess-symbol

FAIL in (commonjs-module-processing-preprocess-symbol) (module_processing_tests.clj:191)
Processed modules are added to :js-module-index
expected: (= {"React" {:name (absolute-module-path "src/test/cljs/reactJS.js"), :module-type :commonjs}, "Circle" {:name (absolute-module-path "src/test/cljs/Circle.js"), :module-type :commonjs}} (:js-module-index (clojure.core/deref cenv)))
  actual: (not (= {"React" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$reactJS", :module-type :commonjs}, "Circle" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$Circle", :module-type :commonjs}} {"React" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$reactJS", :module-type :commonjs}, "Circle" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$Circle", :module-type :commonjs}}))

lein test :only cljs.module-processing-tests/es6-module-processing

FAIL in (es6-module-processing) (module_processing_tests.clj:97)
Processed modules are added to :js-module-index
expected: (= {"es6-hello" {:name (absolute-module-path "src/test/cljs/es6_hello.js"), :module-type :es6}} (:js-module-index (clojure.core/deref cenv)))
  actual: (not (= {"es6-hello" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$es6-hello", :module-type :es6}} {"es6-hello" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$es6-hello", :module-type :es6}}))

lein test :only cljs.module-processing-tests/test-cljs-1822

FAIL in (test-cljs-1822) (module_processing_tests.clj:162)
Processed modules are added to :js-module-index
expected: (= {"React" {:name (absolute-module-path "src/test/cljs/react-min.js"), :module-type :commonjs}, "Circle" {:name (absolute-module-path "src/test/cljs/Circle-min.js"), :module-type :commonjs}} (:js-module-index (clojure.core/deref cenv)))
  actual: (not (= {"React" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$react-min", :module-type :commonjs}, "Circle" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$Circle-min", :module-type :commonjs}} {"React" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$react-min", :module-type :commonjs}, "Circle" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$Circle-min", :module-type :commonjs}}))

lein test :only cljs.module-processing-tests/commonjs-module-processing

FAIL in (commonjs-module-processing) (module_processing_tests.clj:71)
Processed modules are added to :js-module-index
expected: (= {"React" {:name (absolute-module-path "src/test/cljs/reactJS.js"), :module-type :commonjs}, "Circle" {:name (absolute-module-path "src/test/cljs/Circle.js"), :module-type :commonjs}} (:js-module-index (clojure.core/deref cenv)))
  actual: (not (= {"React" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$reactJS", :module-type :commonjs}, "Circle" {:name "module$Users$mfikes$Desktop$dir_with_hypens$clojurescript$src$test$cljs$Circle", :module-type :commonjs}} {"React" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$reactJS", :module-type :commonjs}, "Circle" {:name "module$Users$mfikes$Desktop$dir-with-hypens$clojurescript$src$test$cljs$Circle", :module-type :commonjs}}))

Perhaps related to CLJS-2703.






[CLJS-2730] Docstring error in clojure.core/filter, remove, and take-while Created: 08/Apr/18  Updated: 16/Jun/18  Resolved: 16/Jun/18

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

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: Mike Fikes
Resolution: Completed Votes: 0
Labels: docstring, newbie

Attachments: Text File 0001-CLJS-2730-Fix-docstrings-in-filter-filtev-remove-and.patch    
Patch: Code
Approval: Accepted

 Description   

Same as CLJ-2028 but for ClojureScript.



 Comments   
Comment by Mike Fikes [ 16/Jun/18 10:03 AM ]

Fixed https://github.com/clojure/clojurescript/commit/7528dc79fea372fafa365ee80e4568a3af5f1526





[CLJS-2781] Validate `:global-exports` Created: 16/Jun/18  Updated: 16/Jun/18

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

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


 Description   

Currently we don't validate `:global-exports`. It must map known provides to some symbol that represents a JavaScript global var.






[CLJS-1198] cljs.test may report summary before all async tests complete Created: 12/Apr/15  Updated: 16/Jun/18  Resolved: 16/Jun/18

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

Type: Defect Priority: Major
Reporter: Jenan Wise Assignee: David Nolen
Resolution: Completed Votes: 1
Labels: None

Attachments: File cljs-1198-1    

 Description   

cljs.test may report summary before all async tests complete.

E.g, if you have an async test that looks like this:

(deftest a-test
  (async done
         (testing "a slow async test"
           (go
             (<! (timeout 1000))
             (is (= 0 1))
             (done)))))

then the report output may look like this:

Ran 1 tests containing 0 assertions.
0 failures, 0 errors.

<1 second elapses>

FAIL in () (cljs_test_with_slow_async_example/core_test.js:201:49)
expected: (= 0 1)
  actual: (not (= 0 1))

Minimal repo: https://github.com/jenanwise/cljs-test-with-slow-async-example



 Comments   
Comment by Leon Grapenthin [ 15/Apr/15 12:28 PM ]

I am quite surre that the problem has been introduced with this commit: https://github.com/clojure/clojurescript/commit/9bf486b22cebf5aba4154d07f3ad52e990ddc305

@David
I don't understand the intent of the commit message "cljs.test needs to default to sync, remove broken validation"

Why should the execution strategy default to :sync?

From my reading of the commit this would imply that, unless one provides map fixtures, tests are executed without support for async testing.

This is what happens. The problem goes away if I one adds e. g.

(use-fixtures :each {:before (fn [_])
:after (fn [_])})

I don't see why you removed the guard around async tests in the :sync execution. Its purpose was to throw when execution strategy is :sync an and async test is encountered.

If you can help with the intent of your commit, I'd be glad to provide the fix for myself. What validation was broken?

Comment by David Nolen [ 15/Apr/15 1:41 PM ]

Leon, when I changed how top-level fn emission worked for cross module code motion even though I could see good code getting generated I couldn't run the tests because of the validation bit. After poking around I couldn't make heads or tails of the invariant the code was trying to maintain and so I removed it. All the tests started working again.

Happy to see the invariants re-introduced if the code more clearly documents intent so I can understand it

Comment by Leon Grapenthin [ 15/Apr/15 2:26 PM ]

Can you specify on what you mean by the invariant?

Comment by David Nolen [ 15/Apr/15 2:28 PM ]

Leon, I have no idea what the check was doing nor why it was done that way, only that it prevented me from successfully running more important tests. So you will have to explain the approach to me

Comment by Leon Grapenthin [ 16/Apr/15 2:51 PM ]

Here I try to give you a quick overview of what is going on in the code you have removed/altered:

It solved the problem brought up in our discussion regarding the CLJS-988: The style in which clojure.test requires fixtures to be written didn't allow one to determine when an async test is over. Hence you came up with this requirement: http://dev.clojure.org/jira/browse/CLJS-988?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#issue-tabs

This is the way I have chosen to implement it:

In test-vars-block we create a block that looks up fixtures in the current env and decides whether to support async testing via execution-strategy.

In any case except for wrapped fixtures we run with support for async testing by executing the provided test functions in a block so that they can return async tests which are then picked up by the block runner. Also, via test-var-block additional code is wrapped around and added after them for reporting purposes.

In the case where wrapped fixtures are provided, we can't just create a test-var-block in the same fashion because flow control is passed to the wrapping fixtures and they don't execute or return a block. The only way work around this is to provide them directly with a function that invokes a nested block runner. Implicitly reusing test-var-block here was a decision made for obvious DRY reasons.

Now if async tests are used in the test function, the nested block runner could return before testing is finished, continuing testing too early. This is why the execution strategy is called sync: It expects the nested block runners to finish synchronously.

Per your requirment, testing should be aborted if an async test is encountered in the latter case. We can only know whether a test is async once it has been called and returned something. I didn't see a way to find out what was returned in the :sync result-expr directly, since test-var doesn't return what the test has returned. Hence I picked to look at what the test has returned in the test-var-block and throw if an async test is returned and async tests are disabled, storing this condition in the test-env. Today I see a strong alternative to that: Directly wrap the :test fn in the var in the :sync result-expr to throw if it returns an async test. It surely seems cleaner. You'd get a true invariant because the test-env would be out of the game. Notice though that anyhting thrown there will be catched by the reporting exception handler in test-var-block and testing would continue, so it has to rethrow to truely abort testing. Directly looking up the test-env in the async macro would have been another alternative which I have discarded for its dirtiness because it requires users to invoke async during testing to work.

I hope this helped you to understand the code. To make the code more understandable one could rename execution-strategy to async-supported? and return a boolean.

In any case, the :async execution-strategy needs to be the default, otherwise returned async test objects are not expanded into the root block and this CLJS-1198 happens.

I can provide a patch with the aforementioned improvements on sunday if you like. Finally I have no idea why the check prevented your tests from running - Can you tell me which tests I can use to potentially reproduce the problem?

Comment by Leon Grapenthin [ 19/Apr/15 8:32 AM ]

Patch notes:

  • changes default execution-strategy back to :async
  • prevents async tests from running when execution-strategy is sync

@David: I had to dissect test-var-block a bit because apparently alter-meta! is broken for vars. Please see commented lines 549 and 552 - Also I couldn't check whether this resolves the issue you had with tests being prevented from running after the compiler changes.

Comment by Sebastian Bensusan [ 01/May/15 3:36 PM ]

Experience report: tested this patch with the problematic repo and some other slow async test cases including fixture variations and it seems to work as expected. It also worked with ClojureScript's own tests (tested on all platforms but JavaScriptCore).

Hope this helps.

Comment by David Nolen [ 05/May/15 6:58 AM ]

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

Comment by Jenan Wise [ 11/May/15 12:31 PM ]

Many thanks!

Comment by Alex Miller [ 25/Sep/17 6:56 AM ]

Just reopened to delete spam comment.





[CLJS-1702] Warning when using private vars Created: 07/Jul/16  Updated: 15/Jun/18

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

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

Attachments: Text File CLJS-1702-0.patch     Text File CLJS-1702-1.patch     Text File CLJS-1702-2.patch     Text File CLJS-1702-3.patch     Text File CLJS-1702-4.patch     Text File CLJS-1702-5.patch     Text File CLJS-1702-6.patch     Text File CLJS-1702-7.patch     Text File CLJS-1702-8.patch     Text File CLJS-1702-9.patch    
Patch: Code and Test
Approval: Vetted

 Description   

Currently no warning or error of any kind is given. Throwing an error and forcing users to go through vars is somewhat less attractive since vars dump information like file, line, etc. A warning would be a simple way to flag users that they are treading into dangerous territory. Downstream tooling error handling can make it a hard error if they like.



 Comments   
Comment by Mike Fikes [ 10/Mar/18 9:22 PM ]

Hey David,

The attached experimental patch explores one way to do this. One interesting concept is the use of a new compiler pragma, in the spirit of *unchecked-if* to selectively turn off the warning for blocks of code. It is also interesting how this pragma is can be used in macros that expand to code which calls private functions in their own runtime namespace.

The unit tests don't all pass, but I thought I'd attach this patch as inspiration for ideas.

The fundamental stuff works fine, and with the interesting stuff largely surrounding macros and how you disable the warning.

Here is a demo of the basic functionality:

cljs.user=> (def ^:private a 3)
#'cljs.user/a
cljs.user=> a
3
cljs.user=> (ns foo.core)
nil
foo.core=> cljs.user/a
WARNING: Use of private Var cljs.user/a at line 1 <cljs repl>
3
foo.core=> @#'cljs.user/a
3
Comment by Mike Fikes [ 11/Mar/18 6:37 AM ]

On further thought, instead of a pragma (implemented via a set! intrinsic on a new core var), perhaps it would be better to use meta, along the lines of ^:deprecation-nowarn, so that any code targeting older compilers could be annotated without breaking that code.

Examples:

(^:private-var-access-nowarn some-lib/some-private-fn arg1 arg2)

or

(let [x ^:private-var-access-nowarn some-lib/some-private-var] ,,,)
Comment by Mike Fikes [ 11/Mar/18 7:40 AM ]

CLJS-1702-1.patch takes the metadata approach. This seems to be simpler (and the tests now pass), and could allow libraries that really don't want to go through the var special to simply annotate. Here is an example such use of pr-writer that could be annotated:

https://github.com/clojure/tools.reader/blob/135a7213a5b837b3b23de422f2004ff7a9975800/src/main/cljs/cljs/tools/reader/impl/utils.cljs#L39

The patch doesn't (yet) deal with referring private vars, so you can still {{(require '[foo.core :refer [a]])}} without a warning being triggered if a is private (and subsequent uses of a don't trigger a warning.

Comment by Mike Fikes [ 11/Mar/18 2:11 PM ]

CLJS-1702-2.patch handles the case that private vars are :refer ed.

It actually doesn't do it when processing the ns form, which was the first path I went down, because that leads to a bit of a circular mess: You need to analyze that form to know what is being :refer ed, but then if you try to check for private var usage in the scope of that code, you have to delay checks anyway, because if you do it too soon, warnings are disabled, and if you do it later you'll inadvertently get double warnings when the compiler kicks in.

Anyway, fighting with that led to a simpler solution in the latest patch, which is to simply put the logic in resolve*. This might hurt perf, so I want to be sure it is very fast, but the functionality ends up working out nicely.

With this code:

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

(def ^:private a 3)

things behave nicely, catching the problem when the referred var is actually used. It also works well with aliases:

cljs.user=> (require '[foo.core :as foo :refer [a]])
nil
cljs.user=> a
WARNING: var: foo.core/a is not public at line 1 <cljs repl>
3
cljs.user=> foo/a
WARNING: var: foo.core/a is not public at line 1 <cljs repl>
3
cljs.user=> @#'a
3
cljs.user=> @#'foo/a
3
cljs.user=> ^:private-var-access-nowarn a
3
cljs.user=> ^:private-var-access-nowarn foo/a
3
Comment by Mike Fikes [ 11/Mar/18 8:13 PM ]

CLJS-1702-3.patch adds unit tests and is generally ready for review.

New public names to ponder are the *cljs-warnings* key used for the warning :private-var-access and the metadata key used to selectively squelch the warning in the event that going through var access is undesired :private-var-access-nowarn.

The publicly visible warning text looks like the following, which aligns with Clojure.

WARNING: var: cljs.tools.reader/char-code is not public at line 93 builds/out-adv/cljs/tools/reader/edn.cljs

In experimenting with this code, you can see quite a bit of private var access in libraries. Usually it is macros making use of private runtime vars, if I had to guess. My initial reaction was that there might need to be a global compiler switch to turn off the feature, but then I realized that this is equivalent to the end user simply disabling the warning :private-var-access via the existing mechanism.

One minor risk with the change is that there remain private var accesses within the shipping code, but I think I've addressed all of them by either using ^:private-var-access-nowarn or switching to go indirectly via var.

There is evidently one bug with the handling of the case in (defmethod error-message :invalid-array-access where the analyzer thinks the first element in the first "list" test constant is a function in operator position, thus triggering the private var use warning, so I simply made a minor rewrite to that code to work around.

Comment by Mike Fikes [ 10/Apr/18 6:18 PM ]

CLJS-1702-4.patch rebaselines

Comment by Mike Fikes [ 10/Apr/18 6:24 PM ]

Given that ^:private-var-access-nowarn would end up in code, perhaps a very short name like ^:private-nowarn would be better? (This seems to be in line with ^:deprecation-nowarn.)

Comment by Mike Fikes [ 15/Apr/18 7:37 AM ]

CLJS-1702-5.patch rebaselines

Comment by Mike Fikes [ 16/Apr/18 11:42 AM ]

Assigning back to me to work on an issue where, if you instrument a private var, then it triggers a warning when doing the set! call. (In Clojure you can instrument private vars without any issue.)

Comment by Mike Fikes [ 16/Apr/18 2:38 PM ]

CLJS-1702-6.patch adds a few fixes that allow for instrumenting private Vars, which includes ensuring that client calls to the analyzer API to resolve vars don't trigger the private var warning, as well as a similar tweak needed so that syntax quote expansion on private vars doesn't trigger a warning.

Comment by Mike Fikes [ 16/Apr/18 7:11 PM ]

CLJS-1702-7.patch adds suppression for a couple of warnings that are only visible in self-hosted ClojureScript surrounding accessing cljs.spec.alpha/registry-ref from the cljs.spec.test.alpha namespace.

Comment by Mike Fikes [ 20/Apr/18 7:58 AM ]

TRDR-52 takes care of a private var warning in upstream tools.reader.

Comment by Mike Fikes [ 28/May/18 7:47 AM ]

Site documentation PR: https://github.com/clojure/clojurescript-site/pull/235

Comment by David Nolen [ 15/Jun/18 2:09 PM ]

Let's drop the metadata thing. I don't see why the var access pattern isn't satisfactory for that case.

Comment by Mike Fikes [ 15/Jun/18 4:26 PM ]

CLJS-1702-8.patch dispenses with the metadata.

There are two odd cases that arose in this last patch:

  1. Since the private checked-get (and friends) specifically trigger analysis warnings based on their symbol (see https://github.com/clojure/clojurescript/blob/6950aff480174a25a77c2308aa87a099a774a6e8/src/main/clojure/cljs/analyzer.cljc#L3558), attempting to use var indirection to avoid private var warnings on them defeats the strategy of triggering the logic on those symbols. The latest patch fixes that by piling on a little more special handling for those symbols, suppressing the private var warning for them.
  2. If you spec some private functions and then, from another namespace, enable spec instrumentation, the macros involved end up calling set! on the relevant symbols, and, since they are private, the private var warning will trigger. I couldn't think of a clean way to cope with this, so the revised patch takes the heavy-handed approach of simply turning off private var access warnings when analyzing set! forms. (Perhaps this is OK: when you are using set! and the target happens to be a var, you are already doing something a bit advanced in your code and presumably you know what you are doing?)
Comment by Mike Fikes [ 15/Jun/18 4:36 PM ]

CLJS-1702-9.patch is the same as CLJS-1702-8.patch, except that it eliminates an explicit deref call that had been added, reverting to using @.

Comment by David Nolen [ 15/Jun/18 4:46 PM ]

Thanks will review.





[CLJS-2693] Have Range implement IChunkedSeq Created: 22/Mar/18  Updated: 15/Jun/18

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

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

Attachments: Text File CLJS-2693-0.patch    

 Description   

When Clojure's range was converted from a lazy seq to a LongRange in CLJ-1515, LongRange was made to implement IChunkedSeq. It seems that this could also be applicable in ClojureScript, with superficial evidence being that by taking this form

(apply + (filter even? (map inc (range 1e6))))

and simply adding a call to vec

(apply + (filter even? (map inc (vec (range 1e6)))))

dramatically speeds it up. Benchmarks are included below.

Note that Alex Miller recalls that the change in Clojure was rather challenging, with difficulty:
"balancing the perf concerns of reducible, sequence, and chunked sequence traversal (all of which are possible and may even interleave) while also avoiding potential overflow/underflow cases was a surprisingly narrow path"

Benchmarking with V8
[x (range 100000)], (apply + (filter even? (map inc x))), 10 runs, 1014 msecs
Benchmarking with SpiderMonkey
[x (range 100000)], (apply + (filter even? (map inc x))), 10 runs, 849 msecs
Benchmarking with JavaScriptCore
[x (range 100000)], (apply + (filter even? (map inc x))), 10 runs, 423 msecs
Benchmarking with Nashorn
[x (range 100000)], (apply + (filter even? (map inc x))), 10 runs, 2386 msecs
Benchmarking with ChakraCore
[x (range 100000)], (apply + (filter even? (map inc x))), 10 runs, 1798 msecs
Benchmarking with V8
[x (vec (range 100000))], (apply + (filter even? (map inc x))), 10 runs, 280 msecs
Benchmarking with SpiderMonkey
[x (vec (range 100000))], (apply + (filter even? (map inc x))), 10 runs, 201 msecs
Benchmarking with JavaScriptCore
[x (vec (range 100000))], (apply + (filter even? (map inc x))), 10 runs, 230 msecs
Benchmarking with Nashorn
[x (vec (range 100000))], (apply + (filter even? (map inc x))), 10 runs, 2954 msecs
Benchmarking with ChakraCore
[x (vec (range 100000))], (apply + (filter even? (map inc x))), 10 runs, 427 msecs


 Comments   
Comment by Mike Fikes [ 22/Mar/18 7:19 PM ]

An initial spike into feasibility shows promise:

With the current build of master (1.10.217) as the baseline for the form in the ticket description, in the Node REPL:

cljs.user=> (time (apply + (filter even? (map inc (range 1e6)))))
"Elapsed time: 1247.869027 msecs"
250000500000

and with the experimental exploratory change in CLJS-2693-0.patch

cljs.user=> (time (apply + (filter even? (map inc (range 1e6)))))
"Elapsed time: 251.344390 msecs"
250000500000
Comment by David Nolen [ 15/Jun/18 4:32 PM ]

Nice! Seems like it just needs a bit more work?

Comment by Mike Fikes [ 15/Jun/18 4:42 PM ]

Yes, work towards taking the spike idea and creating a production-quality change has been in progress over here https://github.com/mfikes/clojurescript/commits/CLJS-2693





[CLJS-2703] module name substitution test fails if hypen in directory path Created: 24/Mar/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

Status: Resolved
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: js-modules

Attachments: Text File CLJS-2703.patch    
Patch: Code and Test
Approval: Accepted

 Description   

Repro: mkdir /tmp/foo-bar, cd /tmp/foo-bar, clone ClojureScript there and go into clojurescript and then

lein test :only cljs.module-processing-tests/test-module-name-substitution

This results in what appears to be a munging-related failure:

FAIL in (test-module-name-substitution) (module_processing_tests.clj:123)
expected: (= (str "goog.provide('my_calculator.core');" crlf "goog.require('cljs.core');" crlf "goog.require('" (absolute-module-path "src/test/cljs/calculator.js" true) "');" crlf) (compile (quote (ns my-calculator.core (:require [calculator :as calc :refer [subtract add] :rename {subtract sub}])))))
  actual: (not (= "goog.provide('my_calculator.core');\ngoog.require('cljs.core');\ngoog.require('module$private$tmp$foo-bar$clojurescript$src$test$cljs$calculator');\n" "goog.provide('my_calculator.core');\ngoog.require('cljs.core');\ngoog.require('module$private$tmp$foo_bar$clojurescript$src$test$cljs$calculator');\n"))

lein test :only cljs.module-processing-tests/test-module-name-substitution

FAIL in (test-module-name-substitution) (module_processing_tests.clj:128)
expected: (= output (compile (quote (calc/add 3 4))))
  actual: (not (= "module$private$tmp$foo-bar$clojurescript$src$test$cljs$calculator[\"default\"].add((3),(4));\n" "module$private$tmp$foo_bar$clojurescript$src$test$cljs$calculator[\"default\"].add((3),(4));\n"))

lein test :only cljs.module-processing-tests/test-module-name-substitution

FAIL in (test-module-name-substitution) (module_processing_tests.clj:129)
expected: (= output (compile (quote (calculator/add 3 4))))
  actual: (not (= "module$private$tmp$foo-bar$clojurescript$src$test$cljs$calculator[\"default\"].add((3),(4));\n" "module$private$tmp$foo_bar$clojurescript$src$test$cljs$calculator[\"default\"].add((3),(4));\n"))

lein test :only cljs.module-processing-tests/test-module-name-substitution

FAIL in (test-module-name-substitution) (module_processing_tests.clj:130)
expected: (= output (compile (quote (add 3 4))))
  actual: (not (= "module$private$tmp$foo-bar$clojurescript$src$test$cljs$calculator[\"default\"].add((3),(4));\n" "module$private$tmp$foo_bar$clojurescript$src$test$cljs$calculator[\"default\"].add((3),(4));\n"))

lein test :only cljs.module-processing-tests/test-module-name-substitution

FAIL in (test-module-name-substitution) (module_processing_tests.clj:131)
expected: (= (str (absolute-module-path "src/test/cljs/calculator.js" true) "[\"default\"].subtract((5),(4));" crlf) (compile (quote (sub 5 4))))
  actual: (not (= "module$private$tmp$foo-bar$clojurescript$src$test$cljs$calculator[\"default\"].subtract((5),(4));\n" "module$private$tmp$foo_bar$clojurescript$src$test$cljs$calculator[\"default\"].subtract((5),(4));\n"))


 Comments   
Comment by Mike Fikes [ 07/Apr/18 3:50 PM ]

Juho's take is that the tests are bad and that the production code is good, where the tests can be fixed by munging - to _ as is done in the supplied patch.

Comment by David Nolen [ 15/Jun/18 4:30 PM ]

fixed https://github.com/clojure/clojurescript/commit/6d23b1f4a8eb5f9b504a40f7dacac16e2bb38773





[CLJS-2731] Failure comparing sorted sets Created: 08/Apr/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

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-2731.patch    
Patch: Code and Test
Approval: Accepted

 Description   

In Clojure: (not= (sorted-set :a) (sorted-set 1)) yields true, but in ClojureScript:

cljs.user=> (not= (sorted-set :a) (sorted-set 1))
Error: Cannot compare :a to 1
	 cljs$core$IComparable$_compare$arity$2 (cljs/core.cljs:10270:14)
	 cljs.core/-compare (cljs/core.cljs:818:22)
	 cljs$core$compare (cljs/core.cljs:2374:5)
	 entry_at (cljs/core.cljs:28479:3)
	 cljs$core$ILookup$_lookup$arity$3 (cljs/core.cljs:9272:24)
	 cljs$core$IFn$_invoke$arity$3 (cljs/core.cljs:1941:30)
	 cljs$core$contains_QMARK_ (cljs/core.cljs:2324:20)
	 cljs.core/tree-map-kv-reduce (cljs/core.cljs:27335:3)
	 cljs$core$IKVReduce$_kv_reduce$arity$3 (cljs/core.cljs:8701:19)
	 cljs.core/-kv-reduce (cljs/core.cljs:700:16)
	 cljs.core/reduce-kv (cljs/core.cljs:2543:8)
	 cljs$core$IEquiv$_equiv$arity$2 (cljs/core.cljs:9239:7)
	 cljs.core/-equiv (cljs/core.cljs:706:21)
	 cljs$core$IFn$_invoke$arity$2 (cljs/core.cljs:1268:19)
	 cljs$core$IFn$_invoke$arity$2 (cljs/core.cljs:3952:16)
	 cljs$core$not_EQ_ (cljs/core.cljs:3949:1)

See CLJ-1242



 Comments   
Comment by Jeremy R Sellars [ 04/May/18 12:30 AM ]
  • The error comes from `compare` when elements cannot be compared in the other set.
  • In both Clojure and ClojureScript, `(compare 1 :a)` throws, so this error should be caught as in CLJ-1242.
  • Both types of sets are affected because they check their own contents with `(contains? other %2)`.
  • The patch includes a few tests.
Comment by David Nolen [ 15/Jun/18 4:28 PM ]

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





[CLJS-2749] Internal compiler error with npm dependency on hc-sticky Created: 08/May/18  Updated: 15/Jun/18

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

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


 Description   

I try to add {:install-deps true :npm-deps {:hc-sticky "2.1.6"} ,,,} to my cljsbuild definition, but then it throws exception:

vlaaad@laptop ~/P/repka> lein cljsbuild once dev                                                                                                                                                          master!+?
Compiling ClojureScript...
Compiling ["resources/public/js/app.js"] from ["src/cljs" "src/cljc" "env/dev/cljs"]...
Compiling ["resources/public/js/app.js"] failed.
java.lang.RuntimeException: INTERNAL COMPILER ERROR.
Please report this problem.

The new child node has previous siblings.
  Node(SCRIPT): /home/vlaaad/Projects/repka/node_modules/hc-sticky/dist/hc-sticky.js:11:0
!function(t,e){"use strict";if("object"==typeof module&&"object"==typeof module.exports){if(!t.document)throw new Error("HC-Sticky requires a browser to run.");module.exports=e(t)}else"function"==typeof define&&define.amd?define("hcSticky",[],e(t)):e(t)}("undefined"!=typeof window?window:this,function(t){"use strict";var e={top:0,bottom:0,bottomEnd:0,innerTop:0,innerSticker:null,stickyClass:"sticky",stickTo:null,followScroll:!0,queries:null,queryFlow:"down",onStart:null,onStop:null,onBeforeResize:null,onResize:null,resizeDebounce:100,disable:!1},o=t.document,n=function(i,s){if("string"==typeof i&&(i=o.querySelector(i)),!i)return!1;var r={},a=n.Helpers,l=i.parentNode;"static"===a.getStyle(l,"position")&&(l.style.position="relative");var c=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a.isEmptyObject(t)&&!a.isEmptyObject(r)||(r=Object.assign({},e,r,t))},f=function(){return r.disable},p=function(){if(r.queries){var o=t.innerWidth,n=r.queryFlow,i=r.queries;if(function(t){r=Object.assign({},e,t||{})}(s),"up"===n)for(var l in i)o>=l&&!a.isEmptyObject(i[l])&&c(i[l]);else{var f=[];for(var p in r.queries){var u={};u[p]=i[p],f.push(u)}for(var d=f.length-1;d>=0;d--){var g=f[d],m=Object.keys(g)[0];o<=m&&!a.isEmptyObject(g[m])&&c(g[m])}}}},u={css:{},position:null,stick:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a.hasClass(i,r.stickyClass)||(!1===d.isAttached&&d.attach(),u.position="fixed",i.style.position="fixed",i.style.left=d.offsetLeft+"px",i.style.width=d.width,void 0===t.bottom?i.style.bottom="auto":i.style.bottom=t.bottom+"px",void 0===t.top?i.style.top="auto":i.style.top=t.top+"px",i.classList?i.classList.add(r.stickyClass):i.className+=" "+r.stickyClass,r.onStart&&r.onStart.call(i,r))},release:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(t.stop=t.stop||!1,!0===t.stop||"fixed"===u.position||null===u.position||!(void 0===t.top&&void 0===t.bottom||void 0!==t.top&&(parseInt(a.getStyle(i,"top"))||0)===t.top||void 0!==t.bottom&&(parseInt(a.getStyle(i,"bottom"))||0)===t.bottom)){!0===t.stop?!0===d.isAttached&&d.detach():!1===d.isAttached&&d.attach();var e=t.position||u.css.position;u.position=e,i.style.position=e,i.style.left=!0===t.stop?u.css.left:d.positionLeft+"px",i.style.width="absolute"!==e?u.css.width:d.width,void 0===t.bottom?i.style.bottom=!0===t.stop?"":"auto":i.style.bottom=t.bottom+"px",void 0===t.top?i.style.top=!0===t.stop?"":"auto":i.style.top=t.top+"px",i.classList?i.classList.remove(r.stickyClass):i.className=i.className.replace(new RegExp("(^|\\b)"+r.stickyClass.split(" ").join("|")+"(\\b|$)","gi")," "),r.onStop&&r.onStop.call(i,r)}}},d={el:o.createElement("div"),offsetLeft:null,positionLeft:null,width:null,isAttached:!1,init:function(){for(var t in u.css)d.el.style[t]=u.css[t];var e=a.getStyle(i);d.offsetLeft=a.offset(i).left-(parseInt(e.marginLeft)||0),d.positionLeft=a.position(i).left,d.width=a.getStyle(i,"width")},attach:function(){l.insertBefore(d.el,i.nextSibling),d.isAttached=!0},detach:function(){d.el=l.removeChild(d.el),d.isAttached=!1}},g=void 0,m=void 0,h=void 0,y=void 0,v=void 0,b=void 0,S=void 0,w=void 0,k=void 0,E=void 0,x=void 0,L=void 0,T=void 0,j=void 0,O=void 0,C=void 0,z=void 0,N=void 0,R=function(){u.css=function(t){var e=a.getCascadedStyle(t),o=a.getStyle(t),n={height:t.offsetHeight+"px",left:e.left,right:e.right,top:e.top,bottom:e.bottom,position:o.position,display:o.display,verticalAlign:o.verticalAlign,boxSizing:o.boxSizing,marginLeft:e.marginLeft,marginRight:e.marginRight,marginTop:e.marginTop,marginBottom:e.marginBottom,paddingLeft:e.paddingLeft,paddingRight:e.paddingRight};return e.float&&(n.float=e.float||"none"),e.cssFloat&&(n.cssFloat=e.cssFloat||"none"),o.MozBoxSizing&&(n.MozBoxSizing=o.MozBoxSizing),n.width="auto"!==e.width?e.width:"border-box"===n.boxSizing||"border-box"===n.MozBoxSizing?t.offsetWidth+"px":o.width,n}(i),d.init(),g=!(!r.stickTo||!("document"===r.stickTo||r.stickTo.nodeType&&9===r.stickTo.nodeType||"object"==typeof r.stickTo&&r.stickTo instanceof("undefined"!=typeof HTMLDocument?HTMLDocument:Document))),m=r.stickTo?g?o:"string"==typeof r.stickTo?o.querySelector(r.stickTo):r.stickTo:l,O=(N=function(){var t=i.offsetHeight+(parseInt(u.css.marginTop)||0)+(parseInt(u.css.marginBottom)||0),e=(O||0)-t;return e>=-1&&e<=1?O:t})(),y=(z=function(){return g?Math.max(o.documentElement.clientHeight,o.body.scrollHeight,o.documentElement.scrollHeight,o.body.offsetHeight,o.documentElement.offsetHeight):m.offsetHeight})(),v=g?0:a.offset(m).top,b=r.stickTo?g?0:a.offset(l).top:v,S=t.innerHeight,C=i.offsetTop-(parseInt(u.css.marginTop)||0),h=r.innerSticker?"string"==typeof r.innerSticker?o.querySelector(r.innerSticker):r.innerSticker:null,w=isNaN(r.top)&&r.top.indexOf("%")>-1?parseFloat(r.top)/100*S:r.top,k=isNaN(r.bottom)&&r.bottom.indexOf("%")>-1?parseFloat(r.bottom)/100*S:r.bottom,E=h?h.offsetTop:r.innerTop?r.innerTop:0,x=isNaN(r.bottomEnd)&&r.bottomEnd.indexOf("%")>-1?parseFloat(r.bottomEnd)/100*S:r.bottomEnd,L=v-w+E+C},H=t.pageYOffset||o.documentElement.scrollTop,A=0,B=void 0,I=function(){O=N(),y=z(),T=v+y-w-x,j=O>S;var e=t.pageYOffset||o.documentElement.scrollTop,n=Math.round(a.offset(i).top),s=n-e,c=void 0;B=e<H?"up":"down",A=e-H,H=e,e>L?T+w+(j?k:0)-(r.followScroll&&j?0:w)<=e+O-E-(O-E>S-(L-E)&&r.followScroll&&(c=O-S-E)>0?c:0)?u.release({position:"absolute",bottom:b+l.offsetHeight-T-w}):j&&r.followScroll?"down"===B?s+O+k<=S?u.stick({bottom:k}):"fixed"===u.position&&u.release({position:"absolute",top:n-w-L-A+E}):s+E<0&&"fixed"===u.position?u.release({position:"absolute",top:n-w-L+E-A}):n>=e+w-E&&u.stick({top:w-E}):u.stick({top:w-E}):u.release({stop:!0})},q=!1,F=!1,M=function(){q&&(a.event.unbind(t,"scroll",I),q=!1)},D=function(){R(),O>=y?M():(I(),q||(a.event.bind(t,"scroll",I),q=!0))},W=function(){i.style.position="",i.style.left="",i.style.top="",i.style.bottom="",i.style.width="",i.classList?i.classList.remove(r.stickyClass):i.className=i.className.replace(new RegExp("(^|\\b)"+r.stickyClass.split(" ").join("|")+"(\\b|$)","gi")," "),u.css={},u.position=null,!0===d.isAttached&&d.detach()},P=function(){W(),p(),f()?M():D()},V=function(){r.onBeforeResize&&r.onBeforeResize.call(i,r),P(),r.onResize&&r.onResize.call(i,r)},Y=r.resizeDebounce?a.debounce(V,r.resizeDebounce):V,$=function(){F&&(a.event.unbind(t,"resize",Y),F=!1),M()},Q=function(){F||(a.event.bind(t,"resize",Y),F=!0),p(),f()?M():D()};this.options=function(t){return t?r.option||null:Object.assign({},r)},this.reinit=P,this.update=function(t){c(t),s=Object.assign({},s,t||{}),P()},this.attach=Q,this.detach=$,this.destroy=function(){$(),W()},c(s),Q(),a.event.bind(t,"load",P)};if(void 0!==t.jQuery){var i=t.jQuery;i.fn.extend({hcSticky:function(t){return this.length?this.each(function(){var e=i.data(this,"hcSticky");e?e.update(t):(e=new n(this,t),i.data(this,"hcSticky",e))}):this}})}return t.hcSticky=t.hcSticky||n,n}),function(t){"use strict";var e=t.hcSticky,o=t.document;"function"!=typeof Object.assign&&Object.defineProperty(Object,"assign",{value:function(t,e){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var o=Object(t),n=1;n<arguments.length;n++){var i=arguments[n];if(null!=i)for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(o[s]=i[s])}return o},writable:!0,configurable:!0}),Array.prototype.forEach||(Array.prototype.forEach=function(t){var e,o;if(null==this)throw new TypeError("this is null or not defined");var n=Object(this),i=n.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(e=arguments[1]),o=0;o<i;){var s;o in n&&(s=n[o],t.call(e,s,o,n)),o++}});var n=function(){function e(e){var o=t.event;return o.target=o.target||o.srcElement||e,o}var n=o.documentElement,i=function(){};n.addEventListener?i=function(t,e,o){t.addEventListener(e,o,!1)}:n.attachEvent&&(i=function(t,o,n){t[o+n]=n.handleEvent?function(){var o=e(t);n.handleEvent.call(n,o)}:function(){var o=e(t);n.call(t,o)},t.attachEvent("on"+o,t[o+n])});var s=function(){};return n.removeEventListener?s=function(t,e,o){t.removeEventListener(e,o,!1)}:n.detachEvent&&(s=function(t,e,o){t.detachEvent("on"+e,t[e+o]);try{delete t[e+o]}catch(n){t[e+o]=void 0}}),{bind:i,unbind:s}}(),i=function(e,n){return t.getComputedStyle?n?o.defaultView.getComputedStyle(e,null).getPropertyValue(n):o.defaultView.getComputedStyle(e,null):e.currentStyle?n?e.currentStyle[n.replace(/-\w/g,function(t){return t.toUpperCase().replace("-","")})]:e.currentStyle:void 0},s=function(e){var n=e.getBoundingClientRect(),i=t.pageYOffset||o.documentElement.scrollTop,s=t.pageXOffset||o.documentElement.scrollLeft;return{top:n.top+i,left:n.left+s}};e.Helpers={isEmptyObject:function(t){for(var e in t)return!1;return!0},debounce:function(t,e,o){var n=void 0;return function(){var i=this,s=arguments,r=o&&!n;clearTimeout(n),n=setTimeout(function(){n=null,o||t.apply(i,s)},e),r&&t.apply(i,s)}},hasClass:function(t,e){return t.classList?t.classList.contains(e):new RegExp("(^| )"+e+"( |$)","gi").test(t.className)},offset:s,position:function(t){var e=t.offsetParent,o=s(e),n=s(t),r=i(e),a=i(t);return o.top+=parseInt(r.borderTopWidth)||0,o.left+=parseInt(r.borderLeftWidth)||0,{top:n.top-o.top-(parseInt(a.marginTop)||0),left:n.left-o.left-(parseInt(a.marginLeft)||0)}},getStyle:i,getCascadedStyle:function(e){var n=e.cloneNode(!0);n.style.display="none",Array.prototype.slice.call(n.querySelectorAll('input[type="radio"]')).forEach(function(t){t.removeAttribute("name")}),e.parentNode.insertBefore(n,e.nextSibling);var i=void 0;n.currentStyle?i=n.currentStyle:t.getComputedStyle&&(i=o.defaultView.getComputedStyle(n,null));var s={};for(var r in i)!isNaN(r)||"string"!=typeof i[r]&&"number"!=typeof i[r]||(s[r]=i[r]);if(Object.keys(s).length<3){s={};for(var a in i)isNaN(a)||(s[i[a].replace(/-\w/g,function(t){return t.toUpperCase().replace("-","")})]=i.getPropertyValue(i[a]))}if(s.margin||"auto"!==s.marginLeft?s.margin||s.marginLeft!==s.marginRight||s.marginLeft!==s.marginTop||s.marginLeft!==s.marginBottom||(s.margin=s.marginLeft):s.margin="auto",!s.margin&&"0px"===s.marginLeft&&"0px"===s.marginRight){var l=e.offsetLeft-e.parentNode.offsetLeft,c=l-(parseInt(s.left)||0)-(parseInt(s.right)||0),f=e.parentNode.offsetWidth-e.offsetWidth-l-(parseInt(s.right)||0)+(parseInt(s.left)||0)-c;0!==f&&1!==f||(s.margin="auto")}return n.parentNode.removeChild(n),n=null,s},event:n}}(window);
  Parent(ROOT): [source unknown]

	at com.google.common.base.Preconditions.checkArgument(Preconditions.java:134)
	at com.google.javascript.rhino.Node.replaceChild(Node.java:872)
	at com.google.javascript.jscomp.ProcessCommonJSModules$FindImportsAndExports.replaceUmdPatterns(ProcessCommonJSModules.java:1040)
	at com.google.javascript.jscomp.ProcessCommonJSModules.shouldTraverse(ProcessCommonJSModules.java:102)
	at com.google.javascript.jscomp.NodeTraversal.handleScript(NodeTraversal.java:723)
	at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:749)
	at com.google.javascript.jscomp.NodeTraversal.traverseChildren(NodeTraversal.java:843)
	at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:768)
	at com.google.javascript.jscomp.NodeTraversal.traverse(NodeTraversal.java:305)
	at com.google.javascript.jscomp.NodeTraversal.traverseEs6(NodeTraversal.java:680)
	at com.google.javascript.jscomp.ProcessCommonJSModules.process(ProcessCommonJSModules.java:75)
	at com.google.javascript.jscomp.Compiler.whitespaceOnlyPasses(Compiler.java:1040)
	at cljs.closure$convert_js_modules.invokeStatic(closure.clj:1831)
	at cljs.closure$convert_js_modules.invoke(closure.clj:1810)
	at cljs.closure$process_js_modules.invokeStatic(closure.clj:2557)
	at cljs.closure$process_js_modules.invoke(closure.clj:2518)
	at cljs.closure$handle_js_modules.invokeStatic(closure.clj:2672)
	at cljs.closure$handle_js_modules.invoke(closure.clj:2633)
	at cljs.closure$build.invokeStatic(closure.clj:2814)
	at cljs.closure$build.invoke(closure.clj:2718)
	at cljs.build.api$build.invokeStatic(api.clj:208)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljs.build.api$build.invokeStatic(api.clj:195)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljsbuild.compiler$compile_cljs$fn__718.invoke(compiler.clj:61)
	at cljsbuild.compiler$compile_cljs.invokeStatic(compiler.clj:60)
	at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:48)
	at cljsbuild.compiler$run_compiler.invokeStatic(compiler.clj:168)
	at cljsbuild.compiler$run_compiler.invoke(compiler.clj:129)
	at user$eval847$iter__895__899$fn__900$fn__926.invoke(form-init3044140597862699919.clj:1)
	at user$eval847$iter__895__899$fn__900.invoke(form-init3044140597862699919.clj:1)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.RT.seq(RT.java:528)
	at clojure.core$seq__5124.invokeStatic(core.clj:137)
	at clojure.core$dorun.invokeStatic(core.clj:3125)
	at clojure.core$doall.invokeStatic(core.clj:3140)
	at clojure.core$doall.invoke(core.clj:3140)
	at user$eval847.invokeStatic(form-init3044140597862699919.clj:1)
	at user$eval847.invoke(form-init3044140597862699919.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.eval(Compiler.java:7052)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	at clojure.lang.Compiler.loadFile(Compiler.java:7452)
	at clojure.main$load_script.invokeStatic(main.clj:278)
	at clojure.main$init_opt.invokeStatic(main.clj:280)
	at clojure.main$init_opt.invoke(main.clj:280)
	at clojure.main$initialize.invokeStatic(main.clj:311)
	at clojure.main$null_opt.invokeStatic(main.clj:345)
	at clojure.main$null_opt.invoke(main.clj:342)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: The new child node has previous siblings.
	... 55 more
Subprocess failed



 Comments   
Comment by Mike Fikes [ 12/May/18 8:06 AM ]

Hey Vlad, please see https://clojurescript.org/community/reporting-issues regarding creating a minimal repro.

For example, if you were to run the following, what would need to be in src/foo/core.cljs to repro?

clj -m cljs.main -co '{:install-deps true, :npm-deps {:hc-sticky "2.1.6"}}' -O simple -o main.js -t node -c foo.core




[CLJS-2759] Stacktrace when compiling with --compile-opts that includes a space specified via deps.edn alias Created: 25/May/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

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

Type: Defect Priority: Major
Reporter: Graham Carlyle Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: bug


 Description   

Compiling some cljs code using a deps.edn alias with :main-opts to pass the --compile-opts to cljs compiler causes a stracktrace when the --compile-opts EDN string contains a space.

{:deps
 {org.clojure/clojurescript {:mvn/version "1.10.287"}}

 :aliases
 {:build {:main-opts ["-m" "cljs.main"
                      "--compile-opts" "{:optimizations :advanced}"
                      "--compile" "hello-world.core"]}}}

Replacing the spaces with commas makes it work.

{:deps
 {org.clojure/clojurescript {:mvn/version "1.10.287"}}

 :aliases
 {:build {:main-opts ["-m" "cljs.main"
                      "--compile-opts" "{:optimizations,:advanced}"
                      "--compile" "hello-world.core"]}}}

See this git repo for a minimal reproduction of the problem https://github.com/grahamcarlyle/deps.edn-compile-opts-bug

Produces this stack trace

$ clj -Abuild
Exception in thread "main" java.lang.RuntimeException: EOF while reading
	at clojure.lang.Util.runtimeException(Util.java:221)
	at clojure.lang.EdnReader.readDelimitedList(EdnReader.java:746)
	at clojure.lang.EdnReader$MapReader.invoke(EdnReader.java:680)
	at clojure.lang.EdnReader.read(EdnReader.java:145)
	at clojure.lang.EdnReader.read(EdnReader.java:111)
	at clojure.lang.EdnReader.readString(EdnReader.java:67)
	at clojure.edn$read_string.invokeStatic(edn.clj:46)
	at clojure.edn$read_string.invokeStatic(edn.clj:37)
	at clojure.edn$read_string.invoke(edn.clj:37)
	at cljs.cli$compile_opts_opt.invokeStatic(cli.clj:235)
	at cljs.cli$compile_opts_opt.invoke(cli.clj:231)
	at cljs.cli$initialize$fn__6704.invoke(cli.clj:277)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at cljs.cli$initialize.invokeStatic(cli.clj:275)
	at cljs.cli$initialize.invoke(cli.clj:272)
	at cljs.cli$main.invokeStatic(cli.clj:635)
	at cljs.cli$main.doInvoke(cli.clj:623)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)


 Comments   
Comment by Mike Fikes [ 25/May/18 6:16 AM ]

This is actually an issue in tools.deps: TDEPS-56.





[CLJS-2772] Trying to run `cljs.main` repl with `:modules` results in `brepl_deps.js` being `clojure.lang.LazySeq`. Created: 12/Jun/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

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

Type: Defect Priority: Major
Reporter: Garrett Hopper Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None


 Description   

`clj -A:cljs -co '{:modules {:cljs-base {:output-to "out/base.js"}}}'`



 Comments   
Comment by Garrett Hopper [ 12/Jun/18 10:20 PM ]

It appears the actual issue here is that `cljs.closure/build` returns `(nil)` when `opts` includes any value for `:modules`.

Comment by David Nolen [ 15/Jun/18 3:23 PM ]

fixed https://github.com/clojure/clojurescript/commit/343e6aef57b802975fca3fb5fa0fd85a20330d66





[CLJS-2710] High-arity .apply on spec-instrumented function throws "Invalid arity" error Created: 27/Mar/18  Updated: 15/Jun/18

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

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

ClojureScript 1.10.238



 Description   

With ClojureScript 1.10.238, if you call .apply with over 21 arguments on a function that has been instrumented with cljs.spec.test.alpha/instrument, you will get an error about invalid arity. This problem does not occur with ClojureScript 1.9.954.

(require '[cljs.spec.alpha :as s] '[cljs.spec.test.alpha :as stest])

(defn my-fun [& args] (prn :args args))
(s/fdef my-fun :args (s/cat :args (s/* any?)))

(.apply my-fun nil (into-array (range 22)))
;; :args (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21)

(stest/instrument)
(.apply my-fun nil (into-array (range 22)))
;; Error: Invalid arity: 22
;;     at Function.G__10112 [as call] (.../cljs/core.js:6798:7)
;;     at Function.cljs.core.MetaFn.apply (.../cljs/core.js:6829:24)
;;     at repl:1:96

Regular apply works as expected.



 Comments   
Comment by David Nolen [ 27/Mar/18 4:40 PM ]

See CLJS-364 & CLJS-365

Comment by A. R [ 28/Mar/18 1:22 AM ]

Some of these are (commented out) but added in the patch for the apply test suit: CLJS-2147

Comment by David Nolen [ 28/Mar/18 10:35 AM ]

Ah great, thanks for the tests.

Comment by David Nolen [ 10/Jun/18 12:28 PM ]

Revisiting this now that I'm working on CLJS-2761, why do we need to support `.apply`? I don't think this was ever promised.





[CLJS-2736] Elements returned from sets as functions are not the actual elements in the set. Created: 13/Apr/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

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

Type: Defect Priority: Minor
Reporter: Paula Gearon Assignee: David Nolen
Resolution: Completed Votes: 1
Labels: bug


 Description   

When a set called as a function returns an element, then the argument is returned rather than the element of the set. This is apparent when the values have metadata:

=> (def my-set #{(with-meta [:a] {:n 42})})
=> (meta (my-set [:a]))
nil
=> (meta (my-set (with-meta [:a] {:x 1})))
{:x 1}


 Comments   
Comment by Paula Gearon [ 13/Apr/18 2:05 PM ]

As per Enzzo Cavallo, this is in the code for -lookup on PersistentHashSet.
(existing code)

(-lookup [coll v not-found]
    (if (-contains-key? hash-map v)
      v
      not-found))

My suggestion is to use similar code to -lookup on PersistentTreeSet (which does not have this bug).

(suggested code)

(-lookup [coll v not-found]
    (if-let [entry (-find hash-map v)
      (key entry)
      not-found))
Comment by David Nolen [ 15/Jun/18 2:39 PM ]

fixed https://github.com/clojure/clojurescript/commit/6b7e9402dd841eeb63e2bb3ae3b397eced388def





[CLJS-2298] REPLs should automatically load user.(cljs|cljc) files at root of Java classpath Created: 04/Aug/17  Updated: 15/Jun/18  Resolved: 15/Jun/18

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

Type: Enhancement Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Completed Votes: 4
Labels: repl

Attachments: Text File CLJS-2298.patch    
Patch: Code
Approval: Accepted

 Comments   
Comment by Mike Fikes [ 18/May/18 10:44 AM ]

This patch is fairly straightforward. But, coming up with an a way to writing an automated test for it didn't immediately come to me.

To test this, you have to specify an output directory (see CLJS-2752).

If you have, for example:

"src/user.cljc"
(prn ::foo)
(def a 11)

an example use is

$ clj -Acljs/dev -d out -r
:cljs.user/foo
cljs.user=> a
11

Some notes on the implementation:

  • It checks that it is loading a file (and not just a resource found in a JAR)
  • It calls io/file on the resulting resource, because otherwise if you pass the URL directly, the load-file machinery ends up tripping up where the hash added to the user namespace ends up differing in the file name and the `goog.provide` declaration that ends up in the file. (I suppose we don't often call load-file on things that are not actually files.)
  • You can, if you want, put an `ns` form at the top of the user.cljs / user.cljc file to force it to evaluate any forms in that namespace instead. (Otherwise, your forms are evaluated in cljs.user.
  • It wasn't clear to me whether simply loading the first file found was sufficient, or if there should be an attempt to search for other potential such files on the classpath (I'm assuming the common use case is to load just one file).
Comment by Mike Fikes [ 22/May/18 7:59 AM ]

Associated documentation PR: https://github.com/clojure/clojurescript-site/pull/233

Comment by David Nolen [ 15/Jun/18 1:18 PM ]

fixed https://github.com/clojure/clojurescript/commit/9100030be16b4cb792b3b2c124fd41a5f5a67c63





[CLJS-2779] self-host: test-global-exports-cljs-2243 and test-cljs-2287 failing Created: 15/Jun/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

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

Approval: Accepted

 Description   

On master, script/test-self-host:

FAIL in (test-global-exports-cljs-2243) (core-self-test.js:14153:113)
expected: (some? (re-find #"foo\.core\.global\$module\$calculator = goog.global.Calculator;" value))
  actual: (not (some? nil))

FAIL in (test-cljs-2287) (core-self-test.js:14203:377)
expected: (some? (re-find #"foo\.core\.global\$module\$calculator = goog.global.Calculator;\snull;" source))
  actual: (not (some? nil))


 Comments   
Comment by David Nolen [ 15/Jun/18 7:15 AM ]

fixed https://github.com/clojure/clojurescript/commit/18b97ab86484c4f52bcb462fe585b011e6cf37f2





[CLJS-2778] Unit test failure cljs.build-api-tests/test-emit-global-requires-cljs-2214 Created: 14/Jun/18  Updated: 15/Jun/18  Resolved: 15/Jun/18

Status: Resolved
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
Environment:

Windows AppVeyor CI https://ci.appveyor.com/project/mfikes/clojurescript/build/1.0.148#L99
Travis CI https://travis-ci.org/mfikes/clojurescript/builds/392484188#L2265


Approval: Accepted

 Description   
lein test :only cljs.build-api-tests/test-emit-global-requires-cljs-2214

FAIL in (test-emit-global-requires-cljs-2214) (build_api_tests.clj:399)
simplest case, require
expected: (true? (boolean (re-find #"emit_global_requires_test\.core\.global\$module\$react_dom\$server = goog\.global\.ReactDOMServer;" (slurp (io/file out "emit_global_requires_test/core.js")))))
  actual: (not (true? false))
events.js:160
      throw er; // Unhandled 'error' event


 Comments   
Comment by David Nolen [ 15/Jun/18 7:14 AM ]

fixed https://github.com/clojure/clojurescript/commit/18b97ab86484c4f52bcb462fe585b011e6cf37f2





[CLJS-2777] Bump Closure-compiler Created: 14/Jun/18  Updated: 14/Jun/18  Resolved: 14/Jun/18

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

Type: Enhancement Priority: Major
Reporter: Juho Teperi Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-2777.patch    
Approval: Accepted

 Description   

One important fix in the latest Closure-compiler is fix for UMD wrapper detection which incorrectly handled React CJS bundles.

https://github.com/google/closure-compiler/issues/2841
https://github.com/google/closure-compiler/pull/2963



 Comments   
Comment by David Nolen [ 14/Jun/18 12:53 PM ]

fixed https://github.com/clojure/clojurescript/commit/23d97da89232da99a5d42cf6637b70319a01949d





[CLJS-2775] cljs.main: Node modules not installed if -re node Created: 13/Jun/18  Updated: 13/Jun/18  Resolved: 13/Jun/18

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
Environment:

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}


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

 Description   

The following cljs.main use fails, without node_modules being set up, etc.:

clj -m cljs.main -co '{:npm-deps {:left-pad "1.3.0"} :install-deps true}' -d out -re node -e "(require 'left-pad)" -e "(left-pad 3 10 0)"

On the other hand, if you change to -re browser, things work as expected

clj -m cljs.main -co '{:npm-deps {:left-pad "1.3.0"} :install-deps true}' -d out -re browser -e "(require 'left-pad)" -e "(left-pad 3 10 0)"
"0000000003"

And, after node_modules has been set up by the use of -re browser, the first command, based on -re node starts to succeed, so it is as if the logic to install NPM deps is perhaps simply being skipped?



 Comments   
Comment by David Nolen [ 13/Jun/18 4:40 PM ]

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





[CLJS-2767] Externs inference warnings for defrecord and deftype Created: 03/Jun/18  Updated: 13/Jun/18  Resolved: 13/Jun/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   

If you make use of defrecord with externs inference enabled, you end up with several warnings.

Repro:

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

(set! *warn-on-infer* true)

(defrecord Foo [])
$ clj -m cljs.main -co '{:infer-externs true}' -c foo.core
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. other533 -constructor) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. other533 -__extmap) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. Foo -prototype) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs
WARNING: Cannot infer target type in expression (. foo.core/Foo -getBasis) at line 5 /Users/mfikes/Desktop/src/foo/core.cljs

Likewise, making use of deftype results in a warning:

src/bar/core.cljs
(ns bar.core)

(set! *warn-on-infer* true)

(deftype Bar [])
$ clj -m cljs.main -co '{:infer-externs true}' -c bar.core
WARNING: Cannot infer target type in expression (. Bar -getBasis) at line 5 /Users/mfikes/Desktop/CLJS-2767/src/bar/core.c


 Comments   
Comment by David Nolen [ 07/Jun/18 6:35 AM ]

Does this also apply to deftype?

Comment by Mike Fikes [ 07/Jun/18 11:52 AM ]

Updated ticket title / description to cover the warning generated for deftype.

Comment by Thomas Heller [ 07/Jun/18 12:55 PM ]

IIRC case, satisfies?, maybe implements? also produce infer warnings.

(case thing
  :foo :foo)

I fixed a lot of these in shadow-cljs but never got to actually producing a patch for them. At this point I forgot what the changes were though.

Comment by David Nolen [ 13/Jun/18 4:39 PM ]

fixed https://github.com/clojure/clojurescript/commit/1c4eefac5050c8480137d69d3d5b65fd53478cb2





[CLJS-2776] :main validation checks causing unit test failures Created: 13/Jun/18  Updated: 13/Jun/18  Resolved: 13/Jun/18

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

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

Windows Appveyor CI (https://ci.appveyor.com/project/mfikes/clojurescript/build/1.0.144)



 Description   
lein test :only cljs.build-api-tests/cljs-1500-test-modules
889
890ERROR in (cljs-1500-test-modules) (closure.clj:2196)
891Uncaught exception, not in assertion.
892expected: nil
893module.js:478
894    throw err;
895    ^
896
897Error: Cannot find module '@cljs-oss/module-deps'
898    at Function.Module._resolveFilename (module.js:476:15)
899    at Function.Module._load (module.js:424:25)
900    at Module.require (module.js:504:17)
901    at require (internal/module.js:20:19)
902    at [eval]:8:13
903    at ContextifyScript.Script.runInThisContext (vm.js:25:33)
904    at Object.runInThisContext (vm.js:97:38)
905    at Object.<anonymous> ([eval]-wrapper:6:22)
906    at Module._compile (module.js:577:32)
907    at evalScript (bootstrap_node.js:358:27)
908
909  actual: java.lang.AssertionError: Assert failed: :main must be a symbol, got module-test.main instead
910(symbol? main)
911 at cljs.closure$check_main.invokeStatic (closure.clj:2196)
912    cljs.closure$validate_opts.invokeStatic (closure.clj:2822)
913    cljs.closure$build.invokeStatic (closure.clj:2869)
914    cljs.build.api$build.invokeStatic (api.clj:207)
915    cljs.build.api$build.invoke (api.clj:189)
916    cljs.build.api$build.invokeStatic (api.clj:195)
917    cljs.build_api_tests$fn__12182.invokeStatic (build_api_tests.clj:145)
918    cljs.build_api_tests/fn (build_api_tests.clj:140)
919    clojure.test$test_var$fn__9365.invoke (test.clj:716)
920    clojure.test$test_var.invokeStatic (test.clj:716)
921    clojure.test$test_var.invoke (test.clj:707)
922    clojure.test$test_vars$fn__9391$fn__9396.invoke (test.clj:734)
923    clojure.test$default_fixture.invokeStatic (test.clj:686)
924    clojure.test$default_fixture.invoke (test.clj:682)
925    clojure.test$test_vars$fn__9391.invoke (test.clj:734)
926    clojure.test$default_fixture.invokeStatic (test.clj:686)
927    clojure.test$default_fixture.invoke (test.clj:682)
928    clojure.test$test_vars.invokeStatic (test.clj:730)
929    clojure.test$test_all_vars.invokeStatic (test.clj:736)
930    clojure.test$test_ns.invokeStatic (test.clj:757)
931    clojure.test$test_ns.invoke (test.clj:742)
932    user$eval233$fn__294.invoke (form-init2673640628592496285.clj:1)
933    clojure.lang.AFn.applyToHelper (AFn.java:156)
934    clojure.lang.AFn.applyTo (AFn.java:144)
935    clojure.core$apply.invokeStatic (core.clj:659)
936    leiningen.core.injected$compose_hooks$fn__163.doInvoke (form-init2673640628592496285.clj:1)
937    clojure.lang.RestFn.applyTo (RestFn.java:137)
938    clojure.core$apply.invokeStatic (core.clj:657)
939    leiningen.core.injected$run_hooks.invokeStatic (form-init2673640628592496285.clj:1)
940    leiningen.core.injected$prepare_for_hooks$fn__168$fn__169.doInvoke (form-init2673640628592496285.clj:1)
941    clojure.lang.RestFn.applyTo (RestFn.java:137)
942    clojure.lang.AFunction$1.doInvoke (AFunction.java:29)
943    clojure.lang.RestFn.invoke (RestFn.java:408)
944    clojure.core$map$fn__5665.invoke (core.clj:2747)
945    clojure.lang.LazySeq.sval (LazySeq.java:40)
946    clojure.lang.LazySeq.seq (LazySeq.java:49)
947    clojure.lang.Cons.next (Cons.java:39)
948    clojure.lang.RT.next (RT.java:706)
949    clojure.core$next__5186.invokeStatic (core.clj:64)
950    clojure.core$reduce1.invokeStatic (core.clj:936)
951    clojure.core$reduce1.invokeStatic (core.clj:926)
952    clojure.core$merge_with.invokeStatic (core.clj:3051)
953    clojure.core$merge_with.doInvoke (core.clj:3043)
954    clojure.lang.RestFn.applyTo (RestFn.java:139)
955    clojure.core$apply.invokeStatic (core.clj:659)
956    clojure.test$run_tests.invokeStatic (test.clj:767)
957    clojure.test$run_tests.doInvoke (test.clj:767)
958    clojure.lang.RestFn.applyTo (RestFn.java:137)
959    clojure.core$apply.invokeStatic (core.clj:657)
960    user$eval233$fn__306$fn__339.invoke (form-init2673640628592496285.clj:1)
961    user$eval233$fn__306$fn__307.invoke (form-init2673640628592496285.clj:1)
962    user$eval233$fn__306.invoke (form-init2673640628592496285.clj:1)
963    user$eval233.invokeStatic (form-init2673640628592496285.clj:1)
964    user$eval233.invoke (form-init2673640628592496285.clj:1)
965    clojure.lang.Compiler.eval (Compiler.java:7062)
966    clojure.lang.Compiler.eval (Compiler.java:7052)
967    clojure.lang.Compiler.load (Compiler.java:7514)
968    clojure.lang.Compiler.loadFile (Compiler.java:7452)
969    clojure.main$load_script.invokeStatic (main.clj:278)
970    clojure.main$init_opt.invokeStatic (main.clj:280)
971    clojure.main$init_opt.invoke (main.clj:280)
972    clojure.main$initialize.invokeStatic (main.clj:311)
973    clojure.main$null_opt.invokeStatic (main.clj:345)
974    clojure.main$null_opt.invoke (main.clj:342)
975    clojure.main$main.invokeStatic (main.clj:424)
976    clojure.main$main.doInvoke (main.clj:387)
977    clojure.lang.RestFn.applyTo (RestFn.java:137)
978    clojure.lang.Var.applyTo (Var.java:702)
979    clojure.main.main (main.java:37)
980
981lein test cljs.closure-tests
982
983lein test :only cljs.closure-tests/test-cljs-1882-constants-table-is-sorted
984
985ERROR in (test-cljs-1882-constants-table-is-sorted) (closure.clj:2196)
986Uncaught exception, not in assertion.
987expected: nil
988  actual: java.lang.AssertionError: Assert failed: :main must be a symbol, got module-test.main instead
989(symbol? main)
990 at cljs.closure$check_main.invokeStatic (closure.clj:2196)
991    cljs.closure$validate_opts.invokeStatic (closure.clj:2822)
992    cljs.closure$build.invokeStatic (closure.clj:2869)
993    cljs.build.api$build.invokeStatic (api.clj:207)
994    cljs.build.api$build.invoke (api.clj:189)
995    cljs.build.api$build.invokeStatic (api.clj:195)
996    cljs.closure_tests$fn__12567.invokeStatic (closure_tests.clj:61)
997    cljs.closure_tests/fn (closure_tests.clj:56)
998    clojure.test$test_var$fn__9365.invoke (test.clj:716)
999    clojure.test$test_var.invokeStatic (test.clj:716)
1000    clojure.test$test_var.invoke (test.clj:707)
1001    clojure.test$test_vars$fn__9391$fn__9396.invoke (test.clj:734)
1002    clojure.test$default_fixture.invokeStatic (test.clj:686)
1003    clojure.test$default_fixture.invoke (test.clj:682)
1004    clojure.test$test_vars$fn__9391.invoke (test.clj:734)
1005    clojure.test$default_fixture.invokeStatic (test.clj:686)
1006    clojure.test$default_fixture.invoke (test.clj:682)
1007    clojure.test$test_vars.invokeStatic (test.clj:730)
1008    clojure.test$test_all_vars.invokeStatic (test.clj:736)
1009    clojure.test$test_ns.invokeStatic (test.clj:757)
1010    clojure.test$test_ns.invoke (test.clj:742)
1011    user$eval233$fn__294.invoke (form-init2673640628592496285.clj:1)
1012    clojure.lang.AFn.applyToHelper (AFn.java:156)
1013    clojure.lang.AFn.applyTo (AFn.java:144)
1014    clojure.core$apply.invokeStatic (core.clj:659)
1015    leiningen.core.injected$compose_hooks$fn__163.doInvoke (form-init2673640628592496285.clj:1)
1016    clojure.lang.RestFn.applyTo (RestFn.java:137)
1017    clojure.core$apply.invokeStatic (core.clj:657)
1018    leiningen.core.injected$run_hooks.invokeStatic (form-init2673640628592496285.clj:1)
1019    leiningen.core.injected$prepare_for_hooks$fn__168$fn__169.doInvoke (form-init2673640628592496285.clj:1)
1020    clojure.lang.RestFn.applyTo (RestFn.java:137)
1021    clojure.lang.AFunction$1.doInvoke (AFunction.java:29)
1022    clojure.lang.RestFn.invoke (RestFn.java:408)
1023    clojure.core$map$fn__5665.invoke (core.clj:2747)
1024    clojure.lang.LazySeq.sval (LazySeq.java:40)
1025    clojure.lang.LazySeq.seq (LazySeq.java:49)
1026    clojure.lang.Cons.next (Cons.java:39)
1027    clojure.lang.RT.next (RT.java:706)
1028    clojure.core$next__5186.invokeStatic (core.clj:64)
1029    clojure.core$reduce1.invokeStatic (core.clj:936)
1030    clojure.core$reduce1.invokeStatic (core.clj:926)
1031    clojure.core$merge_with.invokeStatic (core.clj:3051)
1032    clojure.core$merge_with.doInvoke (core.clj:3043)
1033    clojure.lang.RestFn.applyTo (RestFn.java:139)
1034    clojure.core$apply.invokeStatic (core.clj:659)
1035    clojure.test$run_tests.invokeStatic (test.clj:767)
1036    clojure.test$run_tests.doInvoke (test.clj:767)
1037    clojure.lang.RestFn.applyTo (RestFn.java:137)
1038    clojure.core$apply.invokeStatic (core.clj:657)
1039    user$eval233$fn__306$fn__339.invoke (form-init2673640628592496285.clj:1)
1040    user$eval233$fn__306$fn__307.invoke (form-init2673640628592496285.clj:1)
1041    user$eval233$fn__306.invoke (form-init2673640628592496285.clj:1)
1042    user$eval233.invokeStatic (form-init2673640628592496285.clj:1)
1043    user$eval233.invoke (form-init2673640628592496285.clj:1)
1044    clojure.lang.Compiler.eval (Compiler.java:7062)
1045    clojure.lang.Compiler.eval (Compiler.java:7052)
1046    clojure.lang.Compiler.load (Compiler.java:7514)
1047    clojure.lang.Compiler.loadFile (Compiler.java:7452)
1048    clojure.main$load_script.invokeStatic (main.clj:278)
1049    clojure.main$init_opt.invokeStatic (main.clj:280)
1050    clojure.main$init_opt.invoke (main.clj:280)
1051    clojure.main$initialize.invokeStatic (main.clj:311)
1052    clojure.main$null_opt.invokeStatic (main.clj:345)
1053    clojure.main$null_opt.invoke (main.clj:342)
1054    clojure.main$main.invokeStatic (main.clj:424)
1055    clojure.main$main.doInvoke (main.clj:387)
1056    clojure.lang.RestFn.applyTo (RestFn.java:137)
1057    clojure.lang.Var.applyTo (Var.java:702)
1058    clojure.main.main (main.java:37)
1059
1060lein test cljs.compiler-tests

Probably https://github.com/clojure/clojurescript/blob/f81c8bb02359befda716a9348ff5a714076c97b6/src/test/clojure/cljs/test_util.clj#L43



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

fixed https://github.com/clojure/clojurescript/commit/43bc1482c4adac00b8d1f4072d3f0b75827b172f





[CLJS-2774] cljs.main: load file fails if NPM deps involved Created: 13/Jun/18  Updated: 13/Jun/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   
src/foo/core.cljs
(ns foo.core
  (:require left-pad))

(defn pad [n]
  (left-pad n 10 0))

We pass -d here to work around CLJS-2752 and CLJS-2666.

$ clj -m cljs.main -co '{:npm-deps {:left-pad "1.3.0"} :install-deps true}' -d out -r
cljs.user=> (load-file "foo/core.cljs")
nil
cljs.user=> (dir foo.core)
pad
nil
cljs.user=> (foo.core/pad 3)
ReferenceError: Can't find variable: foo
cljs.user=> (require 'foo.core)

cljs.user=> (foo.core/pad 3)
"0000000003"

Note that load-file fails (even though it can succeed; see CLJS-2753), while require succeeds.






[CLJS-2773] cljs.main: Extra out directory in path for load-file Created: 13/Jun/18  Updated: 13/Jun/18  Resolved: 13/Jun/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   

When using load-file from a cljs.main REPL, you end up with an extra out in the compiled file path. Otherwise, things work.

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

(def x 3)

We pass -d here to work around CLJS-2752.

$ clj -m cljs.main -co '{:verbose true}' -d out -r
cljs.user=> (load-file "foo/core.cljs")
...
Compiling /Users/mfikes/Desktop/load-file/src/foo/core.cljs to out/out/foo/core.js
nil
cljs.user=> foo.core/x
3


 Comments   
Comment by Mike Fikes [ 13/Jun/18 9:18 AM ]

Duplicate of CLJS-2753.





[CLJS-2754] Broken cli tests Created: 18/May/18  Updated: 12/Jun/18  Resolved: 12/Jun/18

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
Environment:

Linux; Travis


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

 Description   
Testing cljs-cli.test

FAIL in (run-optimized-node-test) (util.clj:68)
expected: (*post-condition* temp-dir)
  actual: false

FAIL in (run-optimized-node-test) (util.clj:99)
expected: (zero? (:exit result))
  actual: (not (zero? 1))
Exception in thread "main" java.lang.NullPointerException
	at cljs.closure$compile_from_jar.invokeStatic(closure.clj:700)
	at cljs.closure$fn__5704.invokeStatic(closure.clj:727)
	at cljs.closure$fn__5704.invoke(closure.clj:712)
	at cljs.closure$fn__5610$G__5603__5617.invoke(closure.clj:541)
	at cljs.closure$build.invokeStatic(closure.clj:2904)
	at cljs.build.api$build.invokeStatic(api.clj:207)
	at cljs.cli$default_compile.invokeStatic(cli.clj:482)
	at cljs.cli$default_compile.invoke(cli.clj:445)
	at cljs.cli$compile_opt.invokeStatic(cli.clj:493)
	at cljs.cli$compile_opt.invoke(cli.clj:491)
	at cljs.cli$main.invokeStatic(cli.clj:634)
	at cljs.cli$main.doInvoke(cli.clj:623)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at cljs.main$_main.invokeStatic(main.clj:53)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at cljs.main.main(Unknown Source)


FAIL in (test-cljs-2650-loader-does-not-exists) (test.clj:89)
expected: (zero? (:exit result))
  actual: (not (zero? 1))

FAIL in (test-cljs-2650-loader-does-not-exists) (test.clj:90)
expected: (str/blank? (:err result))
  actual: (not (str/blank? "Exception in thread \"main\" java.lang.NullPointerException\n\tat cljs.closure$compile_from_jar.invokeStatic(closure.clj:700)\n\tat cljs.closure$fn__5704.invokeStatic(closure.clj:727)\n\tat cljs.closure$fn__5704.invoke(closure.clj:712)\n\tat cljs.closure$fn__5610$G__5603__5617.invoke(closure.clj:541)\n\tat cljs.closure$build.invokeStatic(closure.clj:2904)\n\tat cljs.build.api$build.invokeStatic(api.clj:207)\n\tat cljs.cli$default_compile.invokeStatic(cli.clj:482)\n\tat cljs.cli$default_compile.invoke(cli.clj:445)\n\tat cljs.cli$compile_opt.invokeStatic(cli.clj:493)\n\tat cljs.cli$compile_opt.invoke(cli.clj:491)\n\tat cljs.cli$main.invokeStatic(cli.clj:634)\n\tat cljs.cli$main.doInvoke(cli.clj:623)\n\tat clojure.lang.RestFn.applyTo(RestFn.java:139)\n\tat clojure.core$apply.invokeStatic(core.clj:659)\n\tat cljs.main$_main.invokeStatic(main.clj:53)\n\tat cljs.main$_main.doInvoke(main.clj:52)\n\tat clojure.lang.RestFn.applyTo(RestFn.java:137)\n\tat cljs.main.main(Unknown Source)\n"))

FAIL in (test-cljs-2650-loader-does-not-exists) (test.clj:89)
expected: (zero? (:exit result))
  actual: (not (zero? 1))

FAIL in (test-cljs-2650-loader-does-not-exists) (test.clj:90)
expected: (str/blank? (:err result))
  actual: (not (str/blank? "Exception in thread \"main\" java.lang.NullPointerException\n\tat cljs.closure$compile_from_jar.invokeStatic(closure.clj:700)\n\tat cljs.closure$fn__5704.invokeStatic(closure.clj:727)\n\tat cljs.closure$fn__5704.invoke(closure.clj:712)\n\tat cljs.closure$fn__5610$G__5603__5617.invoke(closure.clj:541)\n\tat cljs.closure$build.invokeStatic(closure.clj:2904)\n\tat cljs.build.api$build.invokeStatic(api.clj:207)\n\tat cljs.cli$default_compile.invokeStatic(cli.clj:482)\n\tat cljs.cli$default_compile.invoke(cli.clj:445)\n\tat cljs.cli$compile_opt.invokeStatic(cli.clj:493)\n\tat cljs.cli$compile_opt.invoke(cli.clj:491)\n\tat cljs.cli$main.invokeStatic(cli.clj:634)\n\tat cljs.cli$main.doInvoke(cli.clj:623)\n\tat clojure.lang.RestFn.applyTo(RestFn.java:139)\n\tat clojure.core$apply.invokeStatic(core.clj:659)\n\tat cljs.main$_main.invokeStatic(main.clj:53)\n\tat cljs.main$_main.doInvoke(main.clj:52)\n\tat clojure.lang.RestFn.applyTo(RestFn.java:137)\n\tat cljs.main.main(Unknown Source)\n"))

FAIL in (compile-test) (util.clj:68)
expected: (*post-condition* temp-dir)
  actual: false

FAIL in (compile-test) (util.clj:99)
expected: (zero? (:exit result))
  actual: (not (zero? 1))
Exception in thread "main" java.lang.NullPointerException
	at cljs.closure$compile_from_jar.invokeStatic(closure.clj:700)
	at cljs.closure$fn__5704.invokeStatic(closure.clj:727)
	at cljs.closure$fn__5704.invoke(closure.clj:712)
	at cljs.closure$fn__5610$G__5603__5617.invoke(closure.clj:541)
	at cljs.closure$build.invokeStatic(closure.clj:2904)
	at cljs.build.api$build.invokeStatic(api.clj:207)
	at cljs.cli$default_compile.invokeStatic(cli.clj:482)
	at cljs.cli$default_compile.invoke(cli.clj:445)
	at cljs.cli$compile_opt.invokeStatic(cli.clj:493)
	at cljs.cli$compile_opt.invoke(cli.clj:491)
	at cljs.cli$main.invokeStatic(cli.clj:634)
	at cljs.cli$main.doInvoke(cli.clj:623)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at cljs.main$_main.invokeStatic(main.clj:53)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at cljs.main.main(Unknown Source)


Ran 13 tests containing 32 assertions.
8 failures, 0 errors.


 Comments   
Comment by Mike Fikes [ 18/May/18 5:46 PM ]

Broke with CLJS-2682 (See https://travis-ci.org/mfikes/clojurescript/builds/380902785).

Comment by Mike Fikes [ 18/May/18 5:54 PM ]

This appears to be the right change. It certainly fixes the broken unit tests.

Comment by David Nolen [ 12/Jun/18 9:53 AM ]

fixed https://github.com/clojure/clojurescript/commit/00b8dea4b373f367ef23dd7b8913c79b26e2fa94





[CLJS-1913] Investigate slow reading / compilation of CLJC files Created: 27/Jan/17  Updated: 12/Jun/18

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

Type: Defect Priority: Minor
Reporter: António Nuno Monteiro Assignee: Mike Fikes
Resolution: Unresolved Votes: 3
Labels: None





[CLJS-2771] Narrow elide "use strict" match Created: 10/Jun/18  Updated: 11/Jun/18  Resolved: 11/Jun/18

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

Type: Enhancement Priority: Major
Reporter: Pieter du Toit Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

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

 Description   

The match for stripping "use strict" should be narrowed to avoid possible issues as described in the issues linked below:

https://github.com/requirejs/r.js/issues/786
https://github.com/requirejs/r.js/issues/689



 Comments   
Comment by Pieter du Toit [ 10/Jun/18 11:51 PM ]

Patch is attached

Comment by David Nolen [ 11/Jun/18 8:36 AM ]

fixed https://github.com/clojure/clojurescript/commit/0ffe3d8f2aaa592e8d5b92e040e3dbfd62ab8b83





[CLJS-2748] Enable *warn-on-reflection* Created: 06/May/18  Updated: 10/Jun/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: Mike Fikes
Resolution: Unresolved Votes: 4
Labels: performance


 Description   

We have *warn-on-reflection* enabled for the cljs.analyzer and cljs.compiler namespaces.

This ticket asks that this also be enabled on other large, performance-critical namespaces, like cljs.closure, where reasonable.

This would help silly perf issues. For example this one call, when revised to avoid reflection by using clojure.string/starts-with?, improves the speed of indexing node_modules by a factor of 2: https://github.com/clojure/clojurescript/blob/132d3aa232921a3cea66f830d61c89be78c581cb/src/main/clojure/cljs/closure.clj#L2464



 Comments   
Comment by David Nolen [ 07/May/18 3:30 PM ]

Sounds good to me!





[CLJS-2769] Eliminate goog.structs.AvlTree.Node in self-parity test Created: 09/Jun/18  Updated: 10/Jun/18  Resolved: 10/Jun/18

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: bootstrap, test

Attachments: Text File CLJS-2769.patch    
Patch: Code and Test
Approval: Screened

 Description   

goog.structs.AvlTree.Node has been removed from the latest Closure library, and this ticket asks that the reference to it be removed from the self-parity test suite.

Repro:

script/bootstrap --closure-library-head

and then

script/test-self-parity

fails with

Caused by: clojure.lang.ExceptionInfo: No such namespace: goog.structs.AvlTree.Node, could not locate goog/structs/AvlTree/Node.cljs, goog/structs/AvlTree/Node.cljc, or JavaScript source providing "goog.structs.AvlTree.Node" in file src/test/self/self_parity/auxiliary.cljs {:tag :cljs/analysis-error}


 Comments   
Comment by David Nolen [ 10/Jun/18 8:54 AM ]

fixed https://github.com/clojure/clojurescript/commit/215cd3c9495b93f4128a7af9cd6ee038b1d67f27





[CLJS-2768] Elide "use strict" from final output Created: 06/Jun/18  Updated: 07/Jun/18  Resolved: 07/Jun/18

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

Type: Defect Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: newbie

Approval: Screened

 Description   

When concatenating scripts containing "use strict"; will globally apply. We should elide this in all cases where we concatenate JavaScript files. We should be careful to replace with equal length whitespace to prevent issues around source mapping. This should be default behavior. We could consider a compiler knob as a separate enhancement.



 Comments   
Comment by David Nolen [ 07/Jun/18 6:28 AM ]

fixed https://github.com/clojure/clojurescript/commit/03455b4ba4338ab05ffccefc9ddb41c8fd128cfa





[CLJS-2763] cljs.core/resolve fails under :advanced compilation (regression) Created: 01/Jun/18  Updated: 06/Jun/18  Resolved: 06/Jun/18

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

Type: Defect Priority: Major
Reporter: Pieter du Toit Assignee: Unassigned
Resolution: Not Reproducible Votes: 0
Labels: None

Approval: Screened

 Description   

The macro cljs.core/resolve does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
build.edn
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
src/demo/a.cljs
(ns demo.a)

(resolve 'demo.foo.b/bar)
src/demo/foo/b.cljs
(ns demo.foo.b)

(defn bar [] :bar)
index.html
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>

The repro can be compiled by running clj -m cljs.main -co build.edn -c



 Comments   
Comment by David Nolen [ 01/Jun/18 1:24 PM ]

See CLJS-2764, it's now no longer clear what the issue in this ticket is. The above case was simply demonstrating failing exists?.

Comment by Pieter du Toit [ 01/Jun/18 11:57 PM ]

I have narrowed the minimal repro down to React v16 being specified as a foreign lib dependency in the target module. Under :advanced compilation and with React v16, the module's compiled js function definitions are not available after the module is loaded. The attempt by the calling module to then invoke the function in the target module fails with the error "Uncaught TypeError: Cannot read property '$cljs$core$IFn$_invoke$arity$0$' of null" .

A minimal repro that produces the error is provided below:

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}
        cljsjs/react {:mvn/version "16.3.2-0"} }}
src/demo/a.cljs
(ns demo.a
  (:require [cljs.loader]))

(cljs.loader/set-loaded! :a)

(cljs.loader/load :b (fn [e]
                       (.log js/console "Invoking b from a")
                       ((resolve 'demo.foo.b/bar))))
src/demo/foo/b.cljs
(ns demo.foo.b
  (:require [cljsjs.react]
            [cljs.loader]))

(defn bar [] (.log js/console "B has been loaded"))

(cljs.loader/set-loaded! :b)
index.html
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
build.clj
(require '[cljs.build.api :as cljs]
         '[cljs.repl :as repl]
         '[cljs.repl.browser :as browser])

(cljs/build
  "src"
  '{:output-dir "out"
    :optimizations :advanced
    :pseudo-names true
    :pretty-print true 
    :modules {:a {:output-to "out/a.js"
                  :entries [demo.a]}
              :b {:output-to "out/b.js"
                  :entries [demo.foo.b]
                  :depends-on #{:a}}}
    :verbose true})

(repl/repl (browser/repl-env)
  :output-dir "out")

It can be launched by running clj build.clj , once it is launched, observe the error message in the browser's console.

React v16's use of a global scope "use strict" directive seems to be the cause. The minimal repro can also be narrowed down further by removing the React dependency and prepending "use strict"; to out/b.js after compilation.

Comment by David Nolen [ 06/Jun/18 3:53 PM ]

See CLJS-2768 for the actual issue.





[CLJS-2331] Extend :global-exports to auto-alias and rewrite occurrences of declared globals Created: 18/Aug/17  Updated: 06/Jun/18

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

Type: Enhancement Priority: Major
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: foreign-libs, global-exports

Approval: Accepted

 Description   

In order to lower the barrier to adopting `:npm-deps` we could push `:global-exports` a bit further. Instead of just using it to support foreign-libs, we can also use it to automatically make libraries node_modules compatible. This can be done by auto generating a namespace alias if not provided and rewriting global access for matching symbols. Some libs may refer to globals without explicit requires and we should warn in that case.






[CLJS-2766] Revisions to exists? fails in self-host Created: 02/Jun/18  Updated: 04/Jun/18  Resolved: 04/Jun/18

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: bootstrap, regression

Attachments: Text File CLJS-2766.patch     Text File CLJS-2766-wip-1.patch    
Patch: Code

 Description   
$ script/test-self-parity
WARNING: Use of undeclared Var cljs.core$macros/segs at line 970 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 971 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/segs at line 971 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/syms at line 972 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 975 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/segs at line 975 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js at line 976 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 976 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js at line 977 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/syms at line 977 /Users/mfikes/Projects/clojurescript/src/main/clojure/cljs/core.cljc
Testing with Node
/Users/mfikes/Projects/clojurescript/builds/out-self-parity/cljs/core$macros.js:2508
return cljs.core$macros.let$.call(null,new cljs.core.PersistentVector(null, 10, 5, cljs.core.PersistentVector.EMPTY_NODE, [x,cljs.core$macros.cond__GT_.call(null,new cljs.core.Keyword(null,"name","name",1843675177).cljs$core$IFn$_invoke$arity$1(cljs.analyzer.resolve_var.call(null,_AMPERSAND_env,x)),cljs.core._EQ_.call(null,"js",cljs.core.namespace.call(null,x)),cljs.core.name),cljs.core$macros.segs,clojure.string.split.call(null,[cljs.core.str.cljs$core$IFn$_invoke$arity$1(clojure.string.replace.call(null,x,/\\//,"."))].join(''),/\./),cljs.core$macros.n,cljs.core.count.call(null,cljs.core$macros.segs),cljs.core$macros.syms,cljs.core.map.call(null,(function (p1__18668_SHARP_){


SyntaxError: Unexpected token ,
    at new Script (vm.js:51:7)
    at createScript (vm.js:136:10)
    at Object.runInThisContext (vm.js:197:10)
    at Module._compile (internal/modules/cjs/loader.js:618:28)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
    at Module.load (internal/modules/cjs/loader.js:566:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
    at Function.Module._load (internal/modules/cjs/loader.js:498:3)
    at Module.require (internal/modules/cjs/loader.js:598:17)
    at require (internal/modules/cjs/helpers.js:11:18)


 Comments   
Comment by Mike Fikes [ 02/Jun/18 2:29 PM ]

The attached patch makes a few tweaks for self-hosted, but doesn't fully solve the issue, so shouldn't be applied. (Sharing info in case anyone has an idea on the remaining issue regarding extra parentheses described below.)

The patch addresses the fundamental issue by using core/let instead of plain let. It also makes two other changes:

  1. The regex used in the string/replace call is changed to simply be a string. If a regex is used, things derail in self-hosted, with an invalid JavaScript regex being produced. I didn't get to the bottom of this, but it is easily worked around by simply using a string pattern in this case.
  2. The symbol being passed to the string/replace call needs to be first turned into a string to make this a valid call (and thus also work properly in ClojureScript).

With these changes, things get farther along when running script/test-self-parity, but you can see that extra (unbalanced) parentheses are injected in the JavaScript generated for exists? calls. Here is an example:

if((typeof (cljs !== 'undefined') && (typeof (cljs.core$macros !== 'undefined') && (typeof (cljs.core$macros.let _LBRACK_G__324 _SHARP_object_LBRACK_cljs$core$name_RBRACK__RBRACK_ G__324) !== 'undefined')){
} else {
...

This leads to Node balking with an Unexpected identifier error. (You can see the JavaScript generated if you revise self-host.test/node-eval to print the source that is being passed to Node to evaluate.

Comment by Mike Fikes [ 02/Jun/18 5:30 PM ]

CLJS-2766.patch addresses the issues for self-host. (If fixes the issue in the previous comment; cond-> needed to be core/cond->.)

No new tests added since existing tests are sufficient when run with script/test-self-parity.

Comment by David Nolen [ 04/Jun/18 9:15 AM ]

fixed https://github.com/clojure/clojurescript/commit/9a4e89efb01669c07d64b328f16fcb3d9edfa198





[CLJS-2765] Git caching creates cljs_deps.js file with relative paths to cache directory on the first try Created: 01/Jun/18  Updated: 02/Jun/18

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

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

Approval: Screened

 Description   

See CLJS-2763 for code to reproduce



 Comments   
Comment by David Nolen [ 01/Jun/18 1:27 PM ]

Quick fix applied to master for now https://github.com/clojure/clojurescript/commit/cae4792015626ca341e03a4fd9154b6705beba1e

Comment by Mike Fikes [ 02/Jun/18 10:21 AM ]

Trying to reproduce this, using the files in the description of CLJS-2763, I'm getting what may be a completely different error (using 1.10.238, or a JAR built prior to the quick fix above, or a JAR built with current master):

$ clj -m cljs.main -co build.edn -c
Options passed to ClojureScript compiler: {:output-dir "out", :closure-variable-map-out #object[java.io.File 0x747d1932 "out/closure_var.map"], :closure-warnings {:check-types :off, :check-variables :off}, :closure-defines {}, :ups-libs nil, :cache-analysis true, :closure-module-roots [], :modules {:a {:output-to "out/a.js", :entries [demo.a]}, :b {:output-to "out/b.js", :entries [demo.foo.b], :depends-on #{:a}}, :cljs-base {:output-to #object[java.io.File 0x3fc05ea2 "out/cljs_base.js"]}}, :optimizations :none, :ups-foreign-libs [], :closure-property-map-in #object[java.io.File 0x7c891ba7 "out/closure_prop.map"], :verbose true, :aot-cache true, :preloads [process.env], :ignore-js-module-exts [".css"], :output-to "out/main.js", :preamble ["cljs/imul.js"], :closure-property-map-out #object[java.io.File 0x6240651f "out/closure_prop.map"], :stable-names true, :ups-externs nil, :opts-cache "cljsc_opts.edn", :source-map true, :cache-analysis-format :transit, :closure-variable-map-in #object[java.io.File 0x3cf7298d "out/closure_var.map"], :emit-constants nil}
Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :-find-sources of protocol: #'cljs.closure/Compilable found for class: nil
	at clojure.core$_cache_protocol_fn.invokeStatic(core_deftype.clj:583)
	at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:575)
	at cljs.closure$fn__4972$G__4954__4979.invoke(closure.clj:543)
	at cljs.closure$fn__5065.invokeStatic(closure.clj:750)
	at cljs.closure$fn__5065.invoke(closure.clj:714)
	at cljs.closure$fn__4972$G__4954__4979.invoke(closure.clj:543)
	at cljs.closure$fn__5075$fn__5076.invoke(closure.clj:761)
	at clojure.core$map$fn__5583$fn__5584.invoke(core.clj:2734)
	at clojure.core.protocols$iter_reduce.invokeStatic(protocols.clj:49)
	at clojure.core.protocols$fn__7839.invokeStatic(protocols.clj:75)
	at clojure.core.protocols$fn__7839.invoke(protocols.clj:75)
	at clojure.core.protocols$fn__7781$G__7776__7794.invoke(protocols.clj:13)
	at clojure.core$transduce.invokeStatic(core.clj:6804)
	at clojure.core$into.invokeStatic(core.clj:6819)
	at clojure.core$into.invoke(core.clj:6807)
	at cljs.closure$fn__5075.invokeStatic(closure.clj:761)
	at cljs.closure$fn__5075.invoke(closure.clj:714)
	at cljs.closure$fn__4972$G__4954__4979.invoke(closure.clj:543)
	at cljs.closure$build$fn__5831.invoke(closure.clj:2902)
	at cljs.closure$build.invokeStatic(closure.clj:2899)
	at cljs.closure$build.invoke(closure.clj:2808)
	at cljs.build.api$build.invokeStatic(api.clj:208)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljs.cli$default_compile.invokeStatic(cli.clj:485)
	at cljs.cli$default_compile.invoke(cli.clj:445)
	at cljs.cli$compile_opt.invokeStatic(cli.clj:493)
	at cljs.cli$compile_opt.invoke(cli.clj:491)
	at cljs.cli$main.invokeStatic(cli.clj:634)
	at cljs.cli$main.doInvoke(cli.clj:623)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)




[CLJS-2764] exists? is not nil safe Created: 01/Jun/18  Updated: 01/Jun/18  Resolved: 01/Jun/18

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

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


 Description   

exists? does not work if the part of the symbol does not yet exist. i.e. `foo.core.b.baz` where `foo.core.b` does not exist.



 Comments   
Comment by David Nolen [ 01/Jun/18 1:23 PM ]

fixed https://github.com/clojure/clojurescript/commit/9f8ad161eda1eb4b0fdb782e593ee9400b4e1f96





[CLJS-2760] browser REPL web server mime-type check is case sensitive Created: 25/May/18  Updated: 01/Jun/18  Resolved: 01/Jun/18

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

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: newbie

Attachments: Text File 0001-CLJS-2760-Make-browser-repl-web-severs-mime-type-cas.patch    
Patch: Code
Approval: Accepted

 Description   

Currently the builtin web server cannot serve files like foo.JPG.



 Comments   
Comment by David Nolen [ 01/Jun/18 11:46 AM ]

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





[CLJS-2762] Insufficient hooks to build tooling around test termination Created: 29/May/18  Updated: 29/May/18

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

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

Approval: Vetted

 Description   

Currently ClojureScript tests cannot communication termination (and thus test failure) to the JVM process. The solution should cover asynchronous test use case.






[CLJS-1627] jsdoc parsing fails to recognize union types, breaking resolution Created: 18/Apr/16  Updated: 28/May/18

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

Type: Defect Priority: Minor
Reporter: Patrick Killean Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: patch

Attachments: Text File CLJS-1627-4.patch     Text File CLJS-1627-5.patch     Text File CLJS-1627-6.patch     Text File CLJS-1627-7.patch    
Patch: Code and Test

 Description   

The Closure Spec For Union Types states that parentheses are necessary for union type expressions. Trying this ...

(defn foo
  "@param {(IBar|IMap)} x"
  [x] 
  ...)

Raises a Closure Error :

...ERROR - Bad type annotation. expected closing }
* @param {user.(IBar|user.IMap)}

This is because comp/resolve-types treats the parentheses as a part of the type tokens and incorrect var resolution occurs as a result. In addition, the compiler emits multiple resolved types separated by "|" characters but does not enclose them in parentheses to create a valid union type.



 Comments   
Comment by Patrick Killean [ 18/Apr/16 4:36 PM ]

This patch includes:

  • comp/resolve-types now removes parentheses when present and emits them when >1 type is detected. This makes parenthesis use optional and existing code remains unbroken (with the added benefit that it may work now)
  • changes to comp/resolve-type
    1. checks for js globals like document or window which are recognized by closure
    2. allows dot.delimited.forms to pass through so we can use types defined in externs and avoid unnecessary resolution
    3. uses ana/resolve-existing-var with a "unresolved jsdoc type" warning
    4. checks if a resolved var is a protocol and warns otherwise. This is more informative than Closure's standard unrecognized type error
  • a test for comp/resolve-types
Comment by David Nolen [ 21/Apr/16 12:45 PM ]

Thanks will try to look more closely at this tomorrow.

Comment by David Nolen [ 23/Apr/16 2:03 PM ]

The patch is getting there, please remove the `js-doc-type` meta stuff. Just extend the signature of resolve-existing-var to take an additional parameter - the confirm-var-exists handler.

Comment by Patrick Killean [ 09/May/16 4:58 PM ]

CLJS-1627-1.patch:
resolve-existing-var now has an additional arity that accepts a missing-var handler passed to confirm-existing-var

Comment by Patrick Killean [ 10/May/16 6:16 AM ]

This has revealed a problem where deftype + defrecord using Object protocols emit resolved names when really they shouldn't. For example : "@implements {cljs.core.async.impl.timers.Object}" --> Bad Type Annotation

Since Object is a special case simply excluding it from the comments should fix it. Another patch incoming

Comment by Patrick Killean [ 10/May/16 7:42 AM ]

CLJS-1627-2.patch:
The emit* methods for deftype and defrecord now filter out Object protocols.

This produced an interesting result! With no more bad type annotations, static analysis can now proceed... and it has alot to say. Theres all kinds of info now about arity discrepencies (particularly cljs.core.IndexedSeq), type mismatches, and more. It even includes a type coverage percentage. Lots to parse here but very cool.

Comment by Patrick Killean [ 18/May/16 4:26 PM ]

CLJS-1627-3.patch:

  • fix require extern
  • add type application support for Array & Object
  • GC likes uppercase for Object & Array, lowercase for string, number.
  • support for explicit nullable types, variable typed arg
  • function type context modifiers this + new

Missing is the GC 'record type' . It also may be useful to fill out the node externs for common types

Comment by Patrick Killean [ 20/May/16 11:42 AM ]

CLJS-1627-4.patch:

  • fix a few problems in last patch
  • add record type support. Everything here should be covered
Comment by Patrick Killean [ 02/Sep/16 8:21 AM ]

update patch

Comment by Mike Fikes [ 19/Nov/17 7:55 PM ]

CLJS-1627-5.patch no longer applies

Comment by Patrick Killean [ 15/Apr/18 6:50 AM ]

patch 6:

  • routes js* comments through comp/emit-comment which has been altered to handle inline comments.
  • Supported tags: param, return, type, implements, typedef, enum, extends, throws, lends, const, this
  • add macro core/goog-typedef. This lets you name a custom + type refer to it in annotations.

More work is needed to support multi-arity fns, but I think this pretty much unlocks basic static type checking

Comment by Mike Fikes [ 15/Apr/18 7:31 AM ]

Hey Patrick, CLJS-1627-6.patch does not apply to master.

Comment by Patrick Killean [ 15/Apr/18 7:42 AM ]

shoulda had coffee first

Comment by Mike Fikes [ 28/May/18 8:15 AM ]

CLJS-1627-7.patch doe not apply to current master





[CLJS-2761] Warn if fn has more than 20 fixed arguments Created: 25/May/18  Updated: 25/May/18

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

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

Approval: Accepted

 Description   

Currently we do not warn if a function declares more than 20 fixed arguments.






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

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

Type: Enhancement Priority: Major
Reporter: A. R Assignee: David Nolen
Resolution: Completed Votes: 7
Labels: performance

Attachments: Text File CLJS-1871.patch    
Patch: Code and Test
Approval: Accepted

 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.


 Comments   
Comment by A. R [ 12/May/17 8:26 AM ]

Similarly, functions that call themselves recursively don't get invoked optimally. Such as:

  • push-tail
  • do-assoc
  • pop-tail
  • tv-push-tail
  • tv-pop-tail

Matters quite a bit for TreeMap kv-reduce + dissoc.

EDIT: Separately addressed: https://dev.clojure.org/jira/browse/CLJS-2038

Comment by Mike Fikes [ 17/May/18 4:24 PM ]

Hey Andre, I'm looking into this, but if you look at the cons example, you can see the issue you describe with 1.9.293:

cljs.user=> *clojurescript-version*
"1.9.293"
cljs.user=> (.-cljs$core$ICollection$_conj$arity$2 (->IndexedSeq [] nil nil))
#object[Function "function (coll,o){
var self__ = this;
var coll__$1 = this;
return (cljs.core.cons.cljs$core$IFn$_invoke$arity$2 ? cljs.core.cons.cljs$core$IFn$_invoke$arity$2(o,coll__$1) : cljs.core.cons.call(null,o,coll__$1));
}"]

But, with 1.10.238 it is no longer there. I haven't yet discovered the reason.

cljs.user=> *clojurescript-version*
"1.10.238"
cljs.user=> (set! *print-fn-bodies* true)
true
cljs.user=> (.-cljs$core$ICollection$_conj$arity$2 (->IndexedSeq [] nil nil))
#object[Function "function (coll,o){
var self__ = this;
var coll__$1 = this;
return cljs.core.cons(o,coll__$1);
}"]
Comment by Thomas Heller [ 17/May/18 5:47 PM ]

IIRC this is related to https://dev.clojure.org/jira/browse/CLJS-1992

If a var is declare'd and used before the actual var is generated it generates non-optimal code.

Consider this example with declare

(declare foo)

(defn bar [a b]
  (foo a b))

(defn foo [a b]
  (+ a b))

;; bar is ineffecient
demo.browser.bar = (function demo$browser$bar(a,b){
return (demo.browser.foo.cljs$core$IFn$_invoke$arity$2 ? demo.browser.foo.cljs$core$IFn$_invoke$arity$2(a,b) : demo.browser.foo.call(null,a,b));
});
demo.browser.foo = (function demo$browser$foo(a,b){
return (a + b);
});

without declare and potentially with :arglists, the code generated for bar is more efficient

(defn foo [a b]
  (+ a b))

(defn bar [a b]
  (foo a b))

;; bar is now efficient
demo.browser.foo = (function demo$browser$foo(a,b){
return (a + b);
});
demo.browser.bar = (function demo$browser$bar(a,b){
return demo.browser.foo(a,b);
});
Comment by A. R [ 18/May/18 12:29 AM ]

Mike, thanks for taking a look. Also make sure you have static fns on. I can reproduce Thomas's example. Though I agree that the examples that I listed in core are for some reason gone... Not sure why.

Comment by Mike Fikes [ 19/May/18 1:03 PM ]

This behavior did indeed change with CLJS-1992.

What happens is that, when core.cljs is compiled, it is done within the scope of a with-core-cljs block.:

https://github.com/clojure/clojurescript/blob/adeaa9be63b7911d4ac0c7765c2ca8fd2aa4d507/src/main/clojure/cljs/compiler.cljc#L1454-L1458

So, in order to compile core.cljs, an initial pass is made to analyze core.cljs (due to with-core-cljs), followed by actual compilation. During compilation, each of the forms in core.cljs is analyzed (again, in this case), but, owing to CLJS-1992, any declare forms encountered during that second analyzis pass no longer eliminate ananlysis data accumulated during the first pass.

This effectively causes things to look like the following, where the second use of cons (during actual compilation) benefits from the analysis produced for (defn cons [] ,,,) in the first analysis pass:

;; Analysis

(declare cons)

(cons ,,,)

(defn cons [] ,,,)

;; Compilation

(declare cons)

(cons ,,,)

(defn cons [],,)

This explains the observed behavior, and implies that changes for this ticket may be limited only to code outside of core (assumig the existing analysis / compilation model remains in place). (We've already been effectively getting the desired benefit for core functions owing to CLJS-1992.)

Comment by Mike Fikes [ 19/May/18 2:01 PM ]

Hey Andre, without any changes it is possible to achieve this with 1.10.238, but with different meta (:fn-var and :method-params):

$ clj -m cljs.main -co '{:static-fns true}' -re node -r
ClojureScript 1.10.238
cljs.user=> (def ^:declared ^:fn-var ^{:method-params ([a b])} foo)
#'cljs.user/foo
cljs.user=> (defn bar [a b] (foo a b))
#'cljs.user/bar
cljs.user=> (set! *print-fn-bodies* true)
true
cljs.user=> bar
#object[cljs$user$bar "function cljs$user$bar(a,b){
return cljs.user.foo(a,b);
}"]

Is the proposal that, whatever ends up being done, this results in public API that ClojureScript users could employ? Or, is this just a "internal" consideration for namespaces that ship with the compiler?

If it is the former, is the proposal the following?

That

(declare ^{:arglists '([a b])} foo)

be an example of public use, with this perhaps being converted internally into a def that essentially makes use of private meta keys:

(def ^:declared ^:fn-var ^{:method-params ([a b])} foo)
Comment by A. R [ 24/May/18 4:24 AM ]

IMO, we shouldn't leak the AST implementation details. I remember that David was ok with the syntax I initially proposed:

(declare ^{:arglists '([a b])} foo)

so this might be as easy as to add some rewriting into the {declare} macro. It's definitely something that other libraries might want to use (eg. datascript).

Thanks for the research on this. Looks like it should be a pretty easy change.

Only question to remain: What about error reporting if declare and a later {defn} don't match? Could lead to ugly runtime errors when a static dispatch is emitted to a particular arity but the {defn} was changed an is now a (eg) a single arity fn. Or maybe that's already covered?

Comment by Mike Fikes [ 24/May/18 11:04 PM ]

Instead of putting it in the declare macro (which is currently reusing the one from Clojure, the attached patch just does a similar thing during analysis. It also adds a new warning that checks for declared vs. defined :arglists mismatches.

The patch also adds :arglists meta to all declare s in code that ships with the compiler, apart from those in cljs.core which we get for free owing to the double analysis described in a previous comment.

Feature documentation PR: https://github.com/clojure/clojurescript-site/pull/234

Demo:

$ clj -A:cljs/dev -co '{:static-fns true}' -r
cljs.user=> (declare ^{:arglists '([x y])} foo)
#'cljs.user/foo
cljs.user=> (defn arity-wrong [] (foo 1))
WARNING: Wrong number of args (1) passed to cljs.user/foo at line 1 <cljs repl>
#'cljs.user/arity-wrong
cljs.user=> (defn arity-right [] (foo 1 2))
#'cljs.user/arity-right
cljs.user=> (set! *print-fn-bodies* true)
true
cljs.user=> arity-right
#object[cljs$user$arity_right "function cljs$user$arity_right(){
return cljs.user.foo((1),(2));
}"]
cljs.user=> (defn foo [x y z])
WARNING: cljs.user/foo declared arglists ([x y]) mismatch defined arglists ([x y z]) at line 1 <cljs repl>
#'cljs.user/foo
cljs.user=> (declare ^{:arglists '([x])} bar)
#'cljs.user/bar
cljs.user=> (defn bar ([x] 1) ([x y] 2))
WARNING: cljs.user/bar declared arglists ([x]) mismatch defined arglists ([x] [x y]) at line 1 <cljs repl>
Comment by Thomas Heller [ 25/May/18 3:50 AM ]

This is fantastic.

Although I'd ask to include the arglists annotations in cljs.core as well where appropriate since shadow-cljs does not do the double-analyze. I'm happy to create a proper patch for those once this is merged. I don't think there are any high-priority cases left and a couple of declares are outdated anyways (e.g. into-array).

Comment by David Nolen [ 25/May/18 12:51 PM ]

fixed https://github.com/clojure/clojurescript/commit/2ad14709f390e4427b30a8ec86eeb05872e5e52c





[CLJS-2638] --serve throws NPE when serving :none Created: 08/Mar/18  Updated: 24/May/18  Resolved: 24/May/18

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

Type: Defect Priority: Minor
Reporter: A. R Assignee: A. R
Resolution: Not Reproducible Votes: 0
Labels: None


 Description   

Doing a `:none` build and then using `--serve` gives me an NPE in `repl-client-js` fn



 Comments   
Comment by David Nolen [ 18/May/18 10:40 AM ]

Can we please get a full command line reproducer so we don't have to guess?

Comment by A. R [ 24/May/18 2:38 AM ]

The command and NPE:

$ clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.189"}} :paths ["tutorials/cljs"]}' -m cljs.main --optimizations none -c hello-world.core  --serve
Serving HTTP on localhost port 9000
Exception in thread "Thread-120" java.lang.NullPointerException
	at clojure.core$deref_future.invokeStatic(core.clj:2292)
	at clojure.core$deref.invokeStatic(core.clj:2312)
	at clojure.core$deref.invoke(core.clj:2298)
	at cljs.repl.browser$repl_client_js.invokeStatic(browser.clj:82)
	at cljs.repl.browser$repl_client_js.invoke(browser.clj:81)
	at cljs.repl.browser$send_repl_client_page.invokeStatic(browser.clj:89)
	at cljs.repl.browser$send_repl_client_page.invoke(browser.clj:84)
	at cljs.repl.server$dispatch_request.invokeStatic(server.clj:191)
	at cljs.repl.server$dispatch_request.invoke(server.clj:182)
	at cljs.repl.server$handle_connection.invokeStatic(server.clj:199)
	at cljs.repl.server$handle_connection.invoke(server.clj:195)
	at cljs.repl.server$server_loop$fn__7041.invoke(server.clj:209)
	at clojure.core$binding_conveyor_fn$fn__5476.invoke(core.clj:2022)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.lang.Thread.run(Thread.java:748)

The NPE happens after accessing localhost:9000 with a browser.

Comment by A. R [ 24/May/18 2:43 AM ]

Seems to be fixed with 1.10.238





[CLJS-2755] Can't generate uri instances Created: 21/May/18  Updated: 21/May/18  Resolved: 21/May/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}
org.clojure/test.check {:mvn/version "0.10.0-alpha2"}}}


Attachments: Text File CLJS-2755.patch    
Patch: Code and Test
Approval: Accepted

 Description   
$ clj -Srepro -m cljs.main -re node -r
ClojureScript 1.10.238
cljs.user=> (require '[clojure.spec.alpha :as s] 'clojure.test.check.generators)
nil
cljs.user=> (s/gen uri?)
repl:13
throw e__6388__auto__;
^

Error: Unable to construct gen at: [] for: function cljs$core$uri_QMARK_(x){
return (x instanceof goog.Uri);
}
    at cljs$spec$alpha$gensub (/private/var/folders/60/ndky5jxj3v3gw_7j1dwq7msw0000gn/T/out213819377331478911568682775483031/cljs/spec/alpha.js:995:8)
    at Function.cljs.spec.alpha.gen.cljs$core$IFn$_invoke$arity$2 (/private/var/folders/60/ndky5jxj3v3gw_7j1dwq7msw0000gn/T/out213819377331478911568682775483031/cljs/spec/alpha.js:1031:31)
    at cljs$spec$alpha$gen (/private/var/folders/60/ndky5jxj3v3gw_7j1dwq7msw0000gn/T/out213819377331478911568682775483031/cljs/spec/alpha.js:1017:28)
    at Function.cljs.spec.alpha.gen.cljs$core$IFn$_invoke$arity$1 (/private/var/folders/60/ndky5jxj3v3gw_7j1dwq7msw0000gn/T/out213819377331478911568682775483031/cljs/spec/alpha.js:1027:28)
    at cljs$spec$alpha$gen (/private/var/folders/60/ndky5jxj3v3gw_7j1dwq7msw0000gn/T/out213819377331478911568682775483031/cljs/spec/alpha.js:1013:28)
    at repl:1:99
    at repl:9:3
    at repl:14:4
    at Script.runInThisContext (vm.js:65:33)
    at Object.runInThisContext (vm.js:197:38)

Relevant: CLJ-1958



 Comments   
Comment by David Nolen [ 21/May/18 4:01 PM ]

fixed https://github.com/clojure/clojurescript/commit/56ea8ee0de17cac909b09e2bdc1281d02e5404c9





[CLJS-1677] Requiring [goog] breaks an :advanced build, but the compiler exits successfully Created: 09/Jun/16  Updated: 21/May/18  Resolved: 21/May/18

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

Type: Defect Priority: Minor
Reporter: Daniel Compton Assignee: David Nolen
Resolution: Completed Votes: 3
Labels: None

Attachments: Text File CLJS-1677.patch    
Patch: Code and Test
Approval: Accepted

 Description   

A single file with the following in it is enough to break a build:

(ns goog-error.core
  (:require [goog]))

with this error

Jun 10, 2016 11:18:03 AM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: ERROR - Duplicate input: file:/Users/danielcompton/.m2/repository/org/clojure/google-closure-library/0.0-20151016-61277aea/google-closure-library-0.0-20151016-61277aea.jar!/goog/base.js

Jun 10, 2016 11:18:03 AM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 1 error(s), 0 warning(s)
ERROR: JSC_DUPLICATE_INPUT. Duplicate input: file:/Users/danielcompton/.m2/repository/org/clojure/google-closure-library/0.0-20151016-61277aea/google-closure-library-0.0-20151016-61277aea.jar!/goog/base.js at (unknown source) line (unknown line) : (unknown column)

however the ClojureScript compiler exits successfully without throwing an error. The build looks successful, but the file produced doesn't work. Should the ClojureScript compiler throw on these kinds of errors, or otherwise indicate failure?



 Comments   
Comment by David Nolen [ 10/Jun/16 8:27 AM ]

We should look into why the namespace validation that checks where a ns exists or not isn't already catching this case.

Comment by Juho Teperi [ 24/Mar/18 4:13 AM ]

Since CLJS-2495 Cljs now throws on Closure errors: https://github.com/clojure/clojurescript/commit/6c2fba9def9bc830ec7f950f14ff4d89db141439

This duplicate input problem is related to add-goog-base, which adds the file always. Maybe the step could be moved earlier, so add-js-sources (which I think adds the source when required by something) wouldn't add duplicate. Or add-goog-base could remove the base file rest of the inputs. I think the reason add-goog-base is such late step, is to ensure that the base file is the first in the list.

https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L2806

Comment by Mike Fikes [ 20/May/18 10:10 AM ]

See comments in attached patch commit message.

Comment by Juho Teperi [ 20/May/18 10:57 AM ]

Looks good to me.

Comment by David Nolen [ 21/May/18 4:00 PM ]

fixed https://github.com/clojure/clojurescript/commit/27c27e0b53f6ef550670d7aed981395a96aae1da





[CLJS-2756] Relative path issue processing node_modules file Created: 21/May/18  Updated: 21/May/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   

The following

clojure -m cljs.main -co '{:npm-deps {"slate" "0.33.6"} :install-deps true}' -e "(require 'slate)"

generates the following exception

Exception in thread "main" java.lang.IllegalArgumentException: /Users/mfikes/node_modules/immutable/dist/immutable.js is not a relative path
	at clojure.java.io$as_relative_path.invokeStatic(io.clj:414)
	at clojure.java.io$file.invokeStatic(io.clj:426)
	at clojure.java.io$file.invoke(io.clj:418)
	at cljs.closure$write_javascript.invokeStatic(closure.clj:1857)
	at cljs.closure$write_javascript.invoke(closure.clj:1850)
	at cljs.closure$process_js_modules$fn__5815.invoke(closure.clj:2560)
	at clojure.lang.ArrayChunk.reduce(ArrayChunk.java:63)
	at clojure.core.protocols$fn__7847.invokeStatic(protocols.clj:136)
	at clojure.core.protocols$fn__7847.invoke(protocols.clj:124)
	at clojure.core.protocols$fn__7807$G__7802__7816.invoke(protocols.clj:19)
	at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
	at clojure.core.protocols$fn__7835.invokeStatic(protocols.clj:75)
	at clojure.core.protocols$fn__7835.invoke(protocols.clj:75)
	at clojure.core.protocols$fn__7781$G__7776__7794.invoke(protocols.clj:13)
	at clojure.core$reduce.invokeStatic(core.clj:6748)
	at clojure.core$reduce.invoke(core.clj:6730)
	at cljs.closure$process_js_modules.invokeStatic(closure.clj:2559)
	at cljs.closure$process_js_modules.invoke(closure.clj:2518)
	at cljs.closure$handle_js_modules.invokeStatic(closure.clj:2672)
	at cljs.closure$handle_js_modules.invoke(closure.clj:2633)
	at cljs.repl$evaluate_form.invokeStatic(repl.cljc:508)
	at cljs.repl$evaluate_form.invoke(repl.cljc:484)
	at cljs.repl$eval_cljs.invokeStatic(repl.cljc:672)
	at cljs.repl$eval_cljs.invoke(repl.cljc:665)
	at cljs.repl$run_inits$fn__6480.invoke(repl.cljc:823)
	at cljs.repl$run_inits.invokeStatic(repl.cljc:821)
	at cljs.repl$run_inits.invoke(repl.cljc:814)
	at cljs.cli$default_main$fn__6799.invoke(cli.clj:340)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1285)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1274)
	at cljs.compiler.api$with_core_cljs.invokeStatic(api.clj:50)
	at cljs.compiler.api$with_core_cljs.invoke(api.clj:34)
	at cljs.compiler.api$with_core_cljs.invokeStatic(api.clj:42)
	at cljs.compiler.api$with_core_cljs.invoke(api.clj:34)
	at cljs.cli$default_main.invokeStatic(cli.clj:326)
	at cljs.cli$default_main.invoke(cli.clj:299)
	at cljs.cli$null_opt.invokeStatic(cli.clj:394)
	at cljs.cli$null_opt.invoke(cli.clj:391)
	at cljs.cli$main.invokeStatic(cli.clj:612)
	at cljs.cli$main.doInvoke(cli.clj:601)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)


 Comments   
Comment by Mike Fikes [ 21/May/18 2:30 PM ]

This failure was evidently related to the fact that I had a node_modules directory sitting in my home directory. Removing it caused the issue above to go away.

Perhaps this is the result of the processing marching outward (I was in a subdirectory of my home directory). If this is a possibility, maybe the ClojureScript compiler can itself handle this corner case? (Or is this just a user error?)





[CLJS-2440] Re-running watch on CLJS source using native modules results in JS error Created: 12/Dec/17  Updated: 19/May/18

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

Type: Defect Priority: Minor
Reporter: Dave Kozma Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: None
Environment:

Mac OS X 10.13.1, ClojureScript 1.9.968-gebdaf6c0 running on Java SE 1.8.0_144, built with Maven 3.5.2



 Description   

I'm trying to use a native NPM module in my CLJS code (in this case, date-fns), and the initial time I try to watch, it works, however on successive watches, it fails with the following error in my console:

base.js:1357 Uncaught Error: Undefined nameToPath for date_fns
    at visitNode (base.js:1357)
    at Object.goog.writeScripts_ (base.js:1369)
    at Object.goog.require (base.js:706)
    at index.html:8

To reproduce, I've created a build script as such:

(require '[cljs.build.api :as b])

(b/watch "src"
  {:main 'npm.core
   :output-to "out/npm.js"
   :output-dir "out"
   :npm-deps {:date-fns "1.29.0"}})

as well as a minimal test file:

(ns npm.core
  (:require [date-fns :as dfn]))

(def now (js/Date.))
(.write js/document "Today is " (dfn/format now "dddd"))

I'm also testing with a local `package.json` file rather than using `install_deps true` - my `package.json` (generated by CLJS) looks like this:

{
  "dependencies": {
    "@cljs-oss/module-deps": "^1.1.1",
    "date-fns": "^1.29.0"
  }
}

When I run:

npm install
java -cp ../clojurescript/target/cljs.jar:src clojure.main watch.clj

everything works fine, however if I CTRL+C and run the same exact command again, I get the error outlined above.

However, if (and only if) I delete the `out` directory and run the command a third time, it works again.

Please let me know if you need any other details.



 Comments   
Comment by Dave Kozma [ 12/Dec/17 11:47 AM ]

Sorry, seemed to mess up on the title and can't seem to edit. The title should be "Re-running watch on CLJS source using native modules results in JS error"

Comment by Dave Kozma [ 12/Dec/17 11:49 AM ]

Additional environment info:

npm -v 5.5.1
node -v v8.4.0

Comment by Andy Parsons [ 22/Dec/17 12:13 PM ]

Noticed that this was switched to priority 4, but this issue is preventing us from using npm dependencies entirely. What does the lower priority reflect?

Comment by Mike Fikes [ 19/May/18 5:10 PM ]

I can't repro. After hitting Ctrl+C and re-running, I get:

$ java -cp cljs.jar:src clojure.main watch.clj
Building ...
... done. Elapsed 3.674686404 seconds
Watching paths: /Users/mfikes/Desktop/test-cljs-2440/src

This is with the shipping 1.9.908 cljs.jar and with Node v9.11.1 and npm 5.6.0.

I've also confirmed that not reproducible with the 1.10.238 JAR.

I also built the 1.9.968 JAR using commit ebdaf6c06c1112a67ba5a12498801c6d858e5a0a and failed to repro.





[CLJS-2369] Undefined nameToPath for bootstrap` when using Twitter's Bootstrap (twbs) Created: 24/Sep/17  Updated: 19/May/18  Resolved: 19/May/18

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

Type: Defect Priority: Minor
Reporter: Corin Lawson Assignee: Mike Fikes
Resolution: Not Reproducible Votes: 2
Labels: npm-deps
Environment:

1.9.946



 Description   

How to reproduce problem

src/cljsbuild_bootstrap4/core.cljs
(ns cljsbuild-bootstrap4.core
  (:require [bootstrap]))

(enable-console-print!)

(println "Hello world!")

(-> ".alert" js/jQuery (.alert "close"))
index.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>cljsbuild-bootstrap4</title>
	<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css"/>
</head>
<body>
	<div class="alert alert-warning alert-dismissible fade show" role="alert">
		<button type="button" class="close" data-dismiss="alert" aria-label="Close">
			<span aria-hidden="true">&times;</span>
		</button>
		<strong>Holy guacamole!</strong> I should be fading.
	</div>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
	<script src="out/main.js"></script>
</body>
</html>
build.clj
(require 'cljs.build.api)

(cljs.build.api/build "src" {:output-to "out/main.js"
                             :main 'cljsbuild-bootstrap4.core
                             :install-deps true
                             :npm-deps {:bootstrap "4.0.0-beta"}})
  1. Copy the 1.9.946 cljs.jar to the current working directory
  2. Run
    java -cp cljs.jar:src clojure.main build.clj
  3. open index.html
  4. Observe console messages.

Expected result

  1. Console should show the following messages:
    Error: Bootstrap dropdown require Popper.js (https://popper.js.org)
    Hello world!
  2. The Bootstrap Alert component should fade from the page resulting in a blank page.
  3. Compiler should produce:
    out/cljs_deps.js
    goog.addDependency("base.js", ['goog'], []);
    goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
    goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
    goog.addDependency("../node_modules/bootstrap/dist/js/bootstrap.js", ['bootstrap'], []); 
    goog.addDependency("../cljsbuild_bootstrap4/core.js", ['cljsbuild_bootstrap4.core'], ['cljs.core', 'bootstrap']);

Actual result

  1. Console shows
    Error: Undefined nameToPath for bootstrap
  2. The Bootstrap Alert component fails to fade from the page and remains on the page.
  3. Compiler produces:
    out/cljs_deps.js
    goog.addDependency("base.js", ['goog'], []);
    goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
    goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
    goog.addDependency("../cljsbuild_bootstrap4/core.js", ['cljsbuild_bootstrap4.core'], ['cljs.core', 'bootstrap']);


 Comments   
Comment by Hendrik Poernama [ 28/Sep/17 7:44 PM ]

I came across the same problem and did some tracing. It looks like 'load-foreign-library' correctly populated the 'provides' key, but 'library-graph-node' failed to get the 'provides'. I also observed that the output of library-graph-node is the one that gets passed to cljs_deps.js

load-foreign-library: /Users/Hendrik/Projects/bugreports/cljsbuild-bootstrap4/node_modules/bootstrap/dist/js/bootstrap.js
provides: ["bootstrap" "bootstrap/dist/js/bootstrap.js" "bootstrap/dist/js/bootstrap"]

load-foreign-library: /Users/Hendrik/Projects/bugreports/cljsbuild-bootstrap4/node_modules/bootstrap/package.json
provides: []

Copying file:/Users/Hendrik/Projects/bugreports/cljsbuild-bootstrap4/node_modules/bootstrap/dist/js/bootstrap.js to out/node_modules/bootstrap/dist/js/bootstrap.js

load-library: out/node_modules/bootstrap/dist/js/bootstrap.js

library-graph-node: /Users/Hendrik/Projects/bugreports/cljsbuild-bootstrap4/out/node_modules/bootstrap/dist/js/bootstrap.js
{:requires [], :provides [],
:url #object[java.net.URL 0x6a0659ac "file:/<snip>/cljsbuild-bootstrap4/out/node_modules/bootstrap/dist/js/bootstrap.js"],
:closure-lib true, :lib-path "out/node_modules/bootstrap/dist/js/bootstrap.js"}

Comment by Hendrik Poernama [ 29/Sep/17 3:31 AM ]

I am also getting the same error when trying to use 'apollo-client'. 'cljs_deps.js' would be missing the 'whatwg-fetch' dependency.

I suspect this is because 'whatwg-fetch' is a polyfill that does not explicitly export anything. I was able to workaround the issue by appending the following lines to the bottom of '<projectdir>/node_modules/whatwg-fetch/fetch.js'

const whatwg_fetch = 1;
export { whatwg_fetch };

I don't know enough to say that this is the same problem, other than the error message being identical. I have not tried adding the same hack to bootstrap.js

Comment by Derek Chiang [ 08/Jan/18 2:03 AM ]

Getting the same error for `ethereumjs-abi` too.

Log from console:

```
base.js:1357 Uncaught Error: Undefined nameToPath for ethereumjs_abi
at visitNode (base.js:1357)
at visitNode (base.js:1355)
at visitNode (base.js:1355)
at Object.goog.writeScripts_ (base.js:1369)
at Object.goog.require (base.js:706)
at (index):46
```

Comment by Mike Fikes [ 19/May/18 4:08 PM ]

Corin, I can't repro. I've also updated the description so that anyone can attempt to repro. (Minimal per https://clojurescript.org/community/reporting-issues)

I get a slightly different out/cljs_deps.js (below), but otherwise, I get the expected behavior as per the ticket description.

out/cljs_deps.js
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../node_modules/bootstrap/dist/js/bootstrap.js", ['module$Users$mfikes$Desktop$minimal$node_modules$bootstrap$dist$js$bootstrap'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../cljsbuild_bootstrap4/core.js", ['cljsbuild_bootstrap4.core'], ['module$Users$mfikes$Desktop$minimal$node_modules$bootstrap$dist$js$bootstrap', 'cljs.core']);
Comment by Mike Fikes [ 19/May/18 4:22 PM ]

Ahh I see what is going on. This is a problem with 1.9.946. No longer reproducible with 1.10.238.





[CLJS-2457] For non-seqable types, seq evals to object info when running tests Created: 03/Jan/18  Updated: 19/May/18  Resolved: 19/May/18

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: test

Attachments: Text File CLJS-2457.patch    
Patch: Code and Test
Approval: Accepted

 Description   

Observing on master and 1.9.946, and as far back as 1.7.28:

(require '[clojure.test :refer [deftest]])

(deftype FooSeq [])

(deftype BarSeq []
  ASeq)

(deftype BazSeq []
  ICounted (-count [_] 0)
  ISequential)

(defprotocol IFooSeq)

(deftype QuuxSeq []
  IFooSeq)

(deftest test-seq
  (prn (seqable? (->FooSeq)))
  (prn (seq (->FooSeq)))
  (prn (seqable? (->BarSeq)))
  (prn (seq (->BarSeq)))
  (prn (seqable? (->BazSeq)))
  (prn (seq (->BazSeq)))
  (prn (seqable? (->QuuxSeq)))
  (prn (seq (->QuuxSeq))))

If you do this in a REPL and call (test-seq) you will get the second test form throwing as expected:

cljs.user=> (test-seq)
false

ERROR in (test-seq) (Error:NaN:NaN)
Uncaught exception, not in assertion.
expected: nil
  actual: #object[Error Error: [object Object] is not ISeqable]
nil

Note that this also behaves properly if you are in a REPL and put this code in a namespace and load it via require while in the REPL:

Have src/foo/core.cljs containing

(ns foo.core
 (:require [clojure.test :refer [deftest]]))

(deftype FooSeq [])

(deftype BarSeq []
  ASeq)

(deftype BazSeq []
  ICounted (-count [_] 0)
  ISequential)

(defprotocol IFooSeq)

(deftype QuuxSeq []
  IFooSeq)

(deftest test-seq
  (prn (seqable? (->FooSeq)))
  (prn (seq (->FooSeq)))
  (prn (seqable? (->BarSeq)))
  (prn (seq (->BarSeq)))
  (prn (seqable? (->BazSeq)))
  (prn (seq (->BazSeq)))
  (prn (seqable? (->QuuxSeq)))
  (prn (seq (->QuuxSeq))))

and then try it at the REPL:

$ java -cp cljs.jar:src clojure.main -m cljs.repl.node
ClojureScript Node.js REPL server listening on 51614
To quit, type: :cljs/quit
cljs.user=> (require 'foo.core)
nil
cljs.user=> (foo.core/test-seq)
false

ERROR in (test-seq) (Error:NaN:NaN)
Uncaught exception, not in assertion.
expected: nil
  actual: #object[Error Error: [object Object] is not ISeqable]
nil

If instead you drop the code (apart from the require form) into the bottom of the cljs.core-test namespace (or, the top of cljs.primitives-test) and run script/test-simple or script/test-self-parity you will see some concerning output. Also note the odd true and false return values.

true
()
false
(["cljs$lang$protocol_mask$partition0$" 32] ["cljs$lang$protocol_mask$partition1$" 0])
false
(["cljs$lang$protocol_mask$partition0$" 16777218] ["cljs$lang$protocol_mask$partition1$" 0] ["cljs$core$ICounted$_count$arity$1" #object[Function]])
true
(["cljs$core_test$IFooSeq$" #js {}])

A simpler case is (prn (seq #js {:a 1 :b 2})) which will print

(["a" 1] ["b" 2])
.



 Comments   
Comment by Mike Fikes [ 03/Jan/18 2:27 PM ]

Root cause is this test intermixing with other things https://github.com/clojure/clojurescript/commit/009db3c7dc45d2a99afd5d89720bca7d2047219d

The reason I wrote this ticket was a result of one assertion in CLJS-2455 failing.

Comment by Mike Fikes [ 03/Jan/18 3:18 PM ]

Attached patch moves the manipulation of object to a separate namespace that is loaded last, and makes the manipulation occur at runtime.

Comment by David Nolen [ 03/Jan/18 8:22 PM ]

fixed https://github.com/clojure/clojurescript/commit/9f04cb2abec3d6425b35c001d6cd311119570a17





[CLJS-2682] Recompile cljs.loader in REPL Created: 21/Mar/18  Updated: 19/May/18  Resolved: 19/May/18

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-2682-keep-loader-state.patch     Text File CLJS-2682-recompile-loader-in-repl.patch    
Approval: Accepted

 Description   

The cljs.loader namespace is compiled after all other sources have
been compiled, because its `module-infos` and `module-uris` vars need
to be populated with information from the compiler.

REPLs should follow a similar strategy, because otherwise it could
happen that the information in `module-infos` and `module-uris` gets
lost.



 Comments   
Comment by Roman Scherer [ 14/Apr/18 4:08 AM ]

I think there are a couple of cases that can lead to the module-infos
and module-uri vars in the loader namespace being cleared out again.

Let's assume the project has been started within a REPL and an initial
compilation of the project has happened. At this point the loader
namespace has been compiled last, with all the inputs of the project
being passed to the cljsc/compile-loader function.

When you work in the REPL the following things can happen:

When you load a file via cljs.repl/load-file and the file references
the loader namespace, a recompilation of the loader namespace is
triggered. In this case the module-infos and module-uris vars get
reset and the information from the initial compile step gets lost.

The same happens if you evaluate a namespace (via
cljs.repl/evaluate-form I think ) form that contains a reference to
the loader namespace.

Comment by Roman Scherer [ 14/Apr/18 4:25 AM ]

I attached a patch, which I am using locally at the moment to at least
work somehow with my project. But it doesn't work 100% yet. I think
what I'm missing is this:

When the cljs.loader project gets compiled initially (after all other
sources have been compiled) we have all inputs available, and they get
passed to cljsc/compile-loader.

I think the problem with my patch is, that I'm not passing all inputs
to cljsc/compile-loader when I recompile the loader from the cljs.repl
namespace.

I think we need to recompile and load the loader namespace in the
cljs.repl/load-file and cljs.repl/evaluate-form namespaces, but I'm
not quite sure how to get access to all the inputs needed by
cljsc/compile-loader at this point.

Comment by Roman Scherer [ 17/Apr/18 6:58 AM ]

I added another patch that keepts the loader state in the compiler state.

Comment by Roman Scherer [ 26/Apr/18 8:23 AM ]

The CLJS-2682-recompile-loader-in-repl.patch merges new module info from the REPL with the previous state.

Comment by David Nolen [ 18/May/18 1:15 PM ]

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

Comment by Mike Fikes [ 18/May/18 5:46 PM ]

See regression CLJS-2754.





[CLJS-2688] cljs.main: Accumulate all meaningful repeated inits Created: 22/Mar/18  Updated: 18/May/18  Resolved: 18/May/18

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

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

Approval: Accepted

 Description   

Currently, if multiple -co or -ro inits are passed, these are merged left to right.

If multiple -w paths are supplied, these can be {{conj}}d into a vector, for example. (Currently the last wins.)



 Comments   
Comment by Mike Fikes [ 22/Mar/18 9:18 AM ]

It appears that -w is the only opt that could benefit from this. For the others "last wins" makes sense. Given that, I think this should depend on CLJS-2681 which would result in a cleaner ability to fundamentally watch a sequence of paths.

Comment by David Nolen [ 18/May/18 3:52 PM ]

fixed https://github.com/clojure/clojurescript/commit/2e15a5cc0d0e32265f86369c3ade17a445dee6cd





[CLJS-2681] Accepting multiple paths to the --watch option for cljs.main Created: 21/Mar/18  Updated: 18/May/18  Resolved: 18/May/18

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

Type: Enhancement Priority: Major
Reporter: Petter Eriksson Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJS-2681-1.patch     Text File CLJS-2681-2.patch     Text File CLJS-2681-2-with-validation.patch     Text File CLJS-2681-3-with-validation.patch     Text File CLJS-2681.patch    
Patch: Code
Approval: Accepted

 Description   

Use case:
I'm trying to use cljs.main to run my tests whenever code changes. My code base has source code in paths "src", "test" and "env/dev", but I can't pass multiple paths to the --watch option for cljs.main.

Right now a valid call looks like this:

clj -m cljs.main --watch src -c

Enhancement:
It'd be nice if we could pass comma separated strings and/or EDN values:

clj -m cljs.main --watch "(src test env/dev)" -c
clj -m cljs.main --watch "[src test env/dev]" -c
clj -m cljs.main --watch '["src" "test" "env/dev"]' -c
clj -m cljs.main --watch "src,test, env/dev" -c


 Comments   
Comment by Petter Eriksson [ 21/Mar/18 10:26 AM ]

Adds a function to cljs.closure that can take a collection of sources/inputs and return a reified cljs.closure/Inputs and cljs.closure/Compilable, such that the value of the :watch option can be multiple paths.

Adds additional checks to the watch-opt funciton that tries to parse the value of "--watch" as an EDN value and a comma separated list.

Comment by David Nolen [ 21/Mar/18 6:51 PM ]

Not interested in the current patch as is. The only thing I would consider is a version that takes colon delimited source paths.

Comment by Petter Eriksson [ 22/Mar/18 5:28 AM ]

CLJS-2681-1.patch
Parses --watch option as a colon separated string if it contains a colon character.

If you like this patch, I can introduce similar error messages for paths within the colon separated string that do not exist.

Comment by Mike Fikes [ 22/Mar/18 7:58 AM ]

I wonder if the delimiter accepted should actually be File/pathSeparator in order to work well with Windows.

Comment by Mike Fikes [ 22/Mar/18 8:29 AM ]

Relevant CLJS-2687 and CLJS-2688.

Comment by Mike Fikes [ 22/Mar/18 9:23 AM ]

Perhaps this work should instead make use of util/split-paths that would be introduced with CLJS-2687.

Furthermore, since this ticket would introduce a nice way to watch multiple paths, CLJS-2688 should be dependent upon it, as it would make that ticket nearly trivial (probably an update-in into as opposed to the assoc currently used to revise [:options :watch].

Comment by Petter Eriksson [ 23/Mar/18 6:49 AM ]

CLJS-2681-2.patch
Uses cljs.util/split-paths. Also, removed (map string/trim) and (filter seq), as it is valid for files to start and end with whitespaces.

CLJS-2681-2-with-validation.patch
Re-writes the validation logic to handle multiple paths, such that paths are always validated and throws meaningful error messages.

Comment by Petter Eriksson [ 23/Mar/18 6:55 AM ]

We could add (filter clojure.string/blank?) to either watch-opt or cljs.util/split-paths such that colon separated strings can start, end and contain multiple colon chars after each other (i.e. "a:::b").

Comment by Mike Fikes [ 23/Mar/18 7:46 AM ]

CLJS-2681-2-with-validation.patch LGTM

Comment by Mike Fikes [ 23/Mar/18 7:56 AM ]

The -help documentation for for the -watch option could be updated in the patch as well. The current string is

Continuously build, only effective with the --compile main option

An additional sentence, following the pattern for -co and -ro could be:

Continuously build, only effective with the --compile main option. 
Specifies a system-dependent path-separated list of directories to watch.

and the parameter name path could be changed to paths.

Comment by Petter Eriksson [ 23/Mar/18 8:26 AM ]

CLJS-2681-3-with-validation.patch
Adjusts doc string to what Mike suggested and edits parameter name form path to paths.

Comment by David Nolen [ 18/May/18 3:44 PM ]

fixed https://github.com/clojure/clojurescript/commit/92c9d60c15c6f9aeef61de0b2c0ab8f117e6341d





[CLJS-2651] Shared AOT cache: Support git deps Created: 12/Mar/18  Updated: 18/May/18  Resolved: 18/May/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 1
Labels: None

Attachments: Text File CLJS-2651-2.patch     Text File CLJS-2651-3.patch     Text File CLJS-2651-4.patch     Text File CLJS-2651.patch    
Patch: Code
Approval: Accepted

 Description   

The shared AOT cache is built on the notion that code in shipping JARs is immutable and therefore compilation artifacts produced from them can be cached and shared. The same is true for code obtained as a git dep.

This ticket asks that the shared AOT cache mechanism be extended to also cache compilation artifacts produced from git deps.



 Comments   
Comment by Mike Fikes [ 12/Mar/18 10:04 AM ]

The attached patch factors out some of the JAR-based caching logic for reuse.

It copies about 7 lines of code from clojure.tools.gitlibs instead of taking on a dep, for the purposes of identifying the users .gitlibs directory.

Otherwise the patch is fairly straightworward: If the file being compiled is a gitlibs file, it will put the compiled output in the cache if not already there, and likewise if not in the output directory, it will copy from the cache.

I tested the patch manually using core.async:

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.161"}
        org.clojure/core.async #_{:mvn/version "0.4.474"}
    {:git/url "https://github.com/clojure/core.async"
                                :sha "082c93f6a86041d6615d0eae9ae35345ab7cf153"}}}
clj -m cljs.main -v -re node -d out -r

Then (require 'clojure.core.async).

Note that files are compiled from the git dep location to the shared AOT cache and then copied to the out dir

Compiling /Users/mfikes/.gitlibs/libs/org.clojure/core.async/082c93f6a86041d6615d0eae9ae35345ab7cf153/src/main/clojure/cljs/core/async.cljs to /Users/mfikes/.cljs/.aot_cache/1.10.161/45CF18A/cljs/core/async.js
Copying cached /Users/mfikes/.cljs/.aot_cache/1.10.161/45CF18A/cljs/core/async.js to out/cljs/core/async.js

Stop and restart REPL.

clj -m cljs.main -v -re node -d out -r

Then (require 'clojure.core.async)

This will exhibit normal quick startup owing to out being populated.

Stop REPL.
Now remove the out dir.
Start REPL:

clj -m cljs.main -v -re node -d out -r

Then (require 'clojure.core.async).

Note that cached files will now be copied as expected

Copying cached /Users/mfikes/.cljs/.aot_cache/1.10.161/45CF18A/cljs/core/async.js to out/cljs/core/async.js

Additionally, if you then revise deps.edn to depend on the core.async shipping JAR, stop REPL and restart and require core async, things will be recompiled in out as needed. The same thing will happen when you switch back to the git dep.

Comment by Mike Fikes [ 16/Mar/18 7:33 AM ]

CLJS-2651-2.patch rebaselines

Comment by Mike Fikes [ 20/Mar/18 6:24 AM ]

CLJS-2651-3.patch rebaselines

Comment by Mike Fikes [ 18/May/18 3:36 PM ]

CLJS-2651-4.patch rebaselines.

Comment by David Nolen [ 18/May/18 3:41 PM ]

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





[CLJS-2728] Ability to disable macro spec checks Created: 08/Apr/18  Updated: 18/May/18

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

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


 Description   

Akin to Clojure's new ability https://github.com/clojure/clojure/commit/3d9b356306db77946bdf4809baeb660f94cec846

Perhaps ClojureScript would employ a new compiler option to control this?



 Comments   
Comment by David Nolen [ 18/May/18 1:03 PM ]

Agreed.





[CLJS-2733] Throw error message if too few or too many args to throw Created: 09/Apr/18  Updated: 18/May/18  Resolved: 18/May/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: compiler

Approval: Accepted

 Description   

Same as CLJ-1456, but for ClojureScript.



 Comments   
Comment by David Nolen [ 18/May/18 1:02 PM ]

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





[CLJS-2701] goog.text.LoremIpsum not available when script/test-self-parity with Closure Library head Created: 24/Mar/18  Updated: 18/May/18  Resolved: 18/May/18

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

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

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

 Description   
Caused by: clojure.lang.ExceptionInfo: No such namespace: goog.text.LoremIpsum, could not locate goog/text/LoremIpsum.cljs, goog/text/LoremIpsum.cljc, or JavaScript source providing "goog.text.LoremIpsum" in file src/test/self/self_parity/auxiliary.cljs {:tag :cljs/analysis-error}

To repro, first script/clean and script/bootstrap --closure-library-head and then script/test-self-parity.

It looks like the root problem is that this is in google-closure-library-third-party-0.0-20170809-b9c14c6b.jar so we probably need to track down how to get that code in place when doing Closure Library head.

$ jar tvf google-closure-library-third-party-0.0-20170809-b9c14c6b.jar
     0 Thu Aug 10 06:50:52 EDT 2017 META-INF/
   123 Thu Aug 10 06:50:50 EDT 2017 META-INF/MANIFEST.MF
     0 Thu Aug 10 06:50:48 EDT 2017 goog/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/svgpan/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/dojo/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/dojo/dom/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/loremipsum/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/loremipsum/text/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/caja/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/caja/string/
     0 Thu Aug 10 06:50:48 EDT 2017 goog/caja/string/html/
 12240 Thu Aug 10 06:50:48 EDT 2017 goog/svgpan/svgpan.js
  7377 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/deferredlist.js
 29390 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/deferred.js
  2611 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/deferred_async_test.js
 28130 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/deferred_test.js
 10469 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/deferredlist_test.js
   551 Thu Aug 10 06:50:48 EDT 2017 goog/mochikit/async/deferred_async_test_dom.html
  1230 Thu Aug 10 06:50:48 EDT 2017 goog/dojo/dom/query_test_dom.html
 53759 Thu Aug 10 06:50:48 EDT 2017 goog/dojo/dom/query.js
  5027 Thu Aug 10 06:50:48 EDT 2017 goog/dojo/dom/query_test.js
  2036 Thu Aug 10 06:50:48 EDT 2017 goog/loremipsum/text/loremipsum_test.js
 27145 Thu Aug 10 06:50:48 EDT 2017 goog/loremipsum/text/loremipsum.js
 18689 Thu Aug 10 06:50:48 EDT 2017 goog/caja/string/html/htmlparser.js
  4020 Thu Aug 10 06:50:48 EDT 2017 goog/caja/string/html/htmlparser_test.js
   922 Thu Aug 10 06:50:48 EDT 2017 AUTHORS
  1245 Thu Aug 10 06:50:48 EDT 2017 README.md
 10173 Thu Aug 10 06:50:48 EDT 2017 LICENSE
     0 Thu Aug 10 06:50:52 EDT 2017 META-INF/maven/
     0 Thu Aug 10 06:50:52 EDT 2017 META-INF/maven/org.clojure/
     0 Thu Aug 10 06:50:52 EDT 2017 META-INF/maven/org.clojure/google-closure-library-third-party/
  5364 Thu Aug 10 06:50:44 EDT 2017 META-INF/maven/org.clojure/google-closure-library-third-party/pom.xml
   146 Thu Aug 10 06:50:50 EDT 2017 META-INF/maven/org.clojure/google-closure-library-third-party/pom.properties


 Comments   
Comment by Mike Fikes [ 24/Mar/18 1:58 PM ]

The attached patch works the third party stuff into the mix. (The third party stuff is actually very few namespaces, but adding it is the right thing to do if we want to ensure that using head matches using the shipping JARs.)

This addresses the issue with goog.text.LoremIpsum but doesn't actually lead to script/test-self-parity ultimately running with the head of Closure Library. CLJS-2702 captures the issue that is encountered at that point.

Comment by Mike Fikes [ 18/May/18 10:59 AM ]

Duplicate of CLJS-2751





[CLJS-2751] script/bootstrap --closure-library-head misses goog/text Created: 10/May/18  Updated: 18/May/18  Resolved: 18/May/18

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: closure-library

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

 Description   

Repro:

$ script/clean
$ script/bootstrap --closure-library-head
$ script/test-self-parity

This will result in

Exception in thread "main" clojure.lang.ExceptionInfo: failed compiling file:src/test/self/self_parity/auxiliary.cljs {:file #object[java.io.File 0x7ed3682 "src/test/self/self_parity/auxiliary.cljs"]}, compiling:(/Users/mfikes/Projects/clojurescript/bin/../bin/cljsc.clj:22:1)
	at clojure.lang.Compiler.load(Compiler.java:7526)
	at clojure.lang.Compiler.loadFile(Compiler.java:7452)
	at clojure.main$load_script.invokeStatic(main.clj:278)
	at clojure.main$script_opt.invokeStatic(main.clj:338)
	at clojure.main$script_opt.invoke(main.clj:333)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
Caused by: clojure.lang.ExceptionInfo: failed compiling file:src/test/self/self_parity/auxiliary.cljs {:file #object[java.io.File 0x7ed3682 "src/test/self/self_parity/auxiliary.cljs"]}
	at clojure.core$ex_info.invokeStatic(core.clj:4739)
	at clojure.core$ex_info.invoke(core.clj:4739)
	at cljs.compiler$compile_file$fn__4662.invoke(compiler.cljc:1565)
	at cljs.compiler$compile_file.invokeStatic(compiler.cljc:1525)
	at cljs.compiler$compile_file.invoke(compiler.cljc:1501)
	at cljs.closure$compile_file.invokeStatic(closure.clj:573)
	at cljs.closure$compile_file.invoke(closure.clj:564)
	at cljs.closure$eval6968$fn__6969.invoke(closure.clj:653)
	at cljs.closure$eval6886$fn__6887$G__6875__6894.invoke(closure.clj:521)
	at cljs.closure$compile_sources$iter__7108__7112$fn__7113.invoke(closure.clj:1013)
	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:706)
	at clojure.core$next__5108.invokeStatic(core.clj:64)
	at clojure.core$dorun.invokeStatic(core.clj:3134)
	at clojure.core$doall.invokeStatic(core.clj:3140)
	at clojure.core$doall.invoke(core.clj:3140)
	at cljs.closure$compile_sources.invokeStatic(closure.clj:1009)
	at cljs.closure$compile_sources.invoke(closure.clj:998)
	at cljs.closure$build.invokeStatic(closure.clj:2830)
	at cljs.closure$build.invoke(closure.clj:2731)
	at cljs.closure$build.invokeStatic(closure.clj:2737)
	at cljs.closure$build.invoke(closure.clj:2731)
	at user$eval7926.invokeStatic(cljsc.clj:23)
	at user$eval7926.invoke(cljsc.clj:22)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	... 9 more
Caused by: clojure.lang.ExceptionInfo: No such namespace: goog.text.LoremIpsum, could not locate goog/text/LoremIpsum.cljs, goog/text/LoremIpsum.cljc, or JavaScript source providing "goog.text.LoremIpsum" in file src/test/self/self_parity/auxiliary.cljs {:tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4739)
	at clojure.core$ex_info.invoke(core.clj:4739)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:699)
	at cljs.analyzer$error.invoke(analyzer.cljc:695)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:697)
	at cljs.analyzer$error.invoke(analyzer.cljc:695)
	at cljs.analyzer$analyze_deps.invokeStatic(analyzer.cljc:2132)
	at cljs.analyzer$analyze_deps.invoke(analyzer.cljc:2106)
	at cljs.analyzer$ns_side_effects.invokeStatic(analyzer.cljc:3481)
	at cljs.analyzer$ns_side_effects.invoke(analyzer.cljc:3476)
	at cljs.analyzer$analyze_STAR_$fn__3158.invoke(analyzer.cljc:3601)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3601)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:3591)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3621)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:3603)
	at cljs.compiler$emit_source.invokeStatic(compiler.cljc:1389)
	at cljs.compiler$emit_source.invoke(compiler.cljc:1368)
	at cljs.compiler$compile_file_STAR_$fn__4632.invoke(compiler.cljc:1470)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1288)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1277)
	at cljs.compiler$compile_file_STAR_.invokeStatic(compiler.cljc:1454)
	at cljs.compiler$compile_file_STAR_.invoke(compiler.cljc:1447)
	at cljs.compiler$compile_file$fn__4662.invoke(compiler.cljc:1550)
	... 34 more


 Comments   
Comment by Mike Fikes [ 10/May/18 11:04 AM ]

The attached patch causes the JARs created from Closure Library HEAD to match what you would get with an actual release with higher fidelity, in particular, ensuring that the third-party namespaces are done correctly.

Comment by David Nolen [ 18/May/18 10:37 AM ]

fixed https://github.com/clojure/clojurescript/commit/0cdbb23abeeabb36c1ce0a6010890aa97da0fad1





[CLJS-2480] Periods at end of analyzer warnings Created: 24/Jan/18  Updated: 18/May/18  Resolved: 18/May/18

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

Type: Defect Priority: Trivial
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: errormsgs

Attachments: Text File CLJS-2480.patch    
Patch: Code
Approval: Accepted

 Description   

Analyzer warnings have "at line xxx" suffixed, and therefore are not standalone sentences. For example:

cljs.user=> (fn ([]) ([]))
WARNING: : Can't have 2 overloads with same arity at line 1 <cljs repl>

There are a couple of warnings that have periods and thus look odd:

cljs.user=> (+ 1 "a")
WARNING: cljs.core/+, all arguments must be numbers, got [number string] instead. at line 1 <cljs repl>
cljs.user=> (defn ^:deprecated foo [])
#'cljs.user/foo
cljs.user=> (foo)
WARNING: cljs.user/foo is deprecated. at line 1 <cljs repl>


 Comments   
Comment by David Nolen [ 18/May/18 10:36 AM ]

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





[CLJS-2618] remove-tap docstring repetition Created: 05/Mar/18  Updated: 18/May/18  Resolved: 18/May/18

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

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

Attachments: Text File 0001-CLJS-2618-Fix-docstring-for-remove-tap.patch    
Patch: Code

 Description   

"Remove f from the tap set the tap set." should probably be "Remove f from the tap set."

See CLJ-2332.



 Comments   
Comment by David Nolen [ 18/May/18 10:35 AM ]

fixed https://github.com/clojure/clojurescript/commit/1d784517cc80201826219e7954233315d659f567





[CLJS-2743] Docstring for sort-by misspells "function" Created: 24/Apr/18  Updated: 18/May/18  Resolved: 18/May/18

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

Type: Defect Priority: Trivial
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: docstring, newbie

Attachments: Text File 0001-CLJS-2743-Fix-docstring-misspelling.patch    
Patch: Code
Approval: Accepted

 Description   

Docstring includes "Comp can be boolean-valued comparison funcion"



 Comments   
Comment by Erik Assum [ 17/May/18 3:46 PM ]

Fixed email address

Comment by David Nolen [ 18/May/18 10:34 AM ]

fixed https://github.com/clojure/clojurescript/commit/0ef73e0d02bdff3d3e6c46c2eaf5cfff9cf155ba





[CLJS-2753] Extra out directory in path with load-file Created: 18/May/18  Updated: 18/May/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   
foo.cljs
(def x 3)

Working with -d:

$ clj -m cljs.main -re node -d out -r
ClojureScript 1.10.238
cljs.user=> (load-file "foo.cljs")
nil
cljs.user=> x
3

You will end up with out/out/cljs/user/fooAD3E4B4.js

Otherwise things appear to work.






[CLJS-2752] load-file fails if no output dir specified Created: 18/May/18  Updated: 18/May/18

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

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

{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}



 Description   
foo.cljs
(def x 3)

Working with -d:

$ clj -m cljs.main -re node -d out -r
ClojureScript 1.10.238
cljs.user=> (load-file "foo.cljs")
nil
cljs.user=> x
3

Failing without:

$ clj -m cljs.main -re node -r
ClojureScript 1.10.238
cljs.user=> (load-file "foo.cljs")
java.lang.IllegalArgumentException: /var/folders/gx/nymj3l7x4zq3gxb97v2zwzb40000gn/T/out7651413336278138652227528048732117/cljs/user/fooAD3E4B4.js is not a relative path
	at clojure.java.io$as_relative_path.invokeStatic(io.clj:414)
	at clojure.java.io$file.invokeStatic(io.clj:426)
	at clojure.java.io$file.invoke(io.clj:418)
	at cljs.closure$compile_file.invokeStatic(closure.clj:572)
	at cljs.closure$compile_file.invoke(closure.clj:564)
	at cljs.closure$fn__5124.invokeStatic(closure.clj:653)
	at cljs.closure$fn__5124.invoke(closure.clj:647)
	at cljs.closure$fn__5052$G__5045__5059.invoke(closure.clj:521)
	at cljs.closure$compile.invokeStatic(closure.clj:557)
	at cljs.closure$compile.invoke(closure.clj:554)
	at cljs.repl$load_file$fn__6378.invoke(repl.cljc:586)
	at cljs.repl$load_file.invokeStatic(repl.cljc:585)
	at cljs.repl$load_file.invoke(repl.cljc:577)
	at cljs.repl$fn__6429$self__6431.invoke(repl.cljc:740)
	at clojure.lang.AFn.applyToHelper(AFn.java:165)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.repl$wrap_self$g__6408.invoke(repl.cljc:724)
	at cljs.repl$repl_STAR_$read_eval_print__6536.invoke(repl.cljc:955)
	at cljs.repl$repl_STAR_$fn__6542$fn__6551.invoke(repl.cljc:998)
	at cljs.repl$repl_STAR_$fn__6542.invoke(repl.cljc:997)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1285)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1274)
	at cljs.repl$repl_STAR_.invokeStatic(repl.cljc:960)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:839)
	at cljs.cli$repl_opt.invokeStatic(cli.clj:290)
	at cljs.cli$repl_opt.invoke(cli.clj:277)
	at cljs.cli$main.invokeStatic(cli.clj:612)
	at cljs.cli$main.doInvoke(cli.clj:601)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)





[CLJS-2433] HTTP server in cljs.browser.repl doesn't serve files with extensions other than specified in ext->mime-type Created: 04/Dec/17  Updated: 17/May/18

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

Type: Defect Priority: Major
Reporter: Yegor Timoshenko Assignee: Yegor Timoshenko
Resolution: Unresolved Votes: 3
Labels: None

Attachments: Text File 0001-CLJS-2433-fallback-to-send-static-use-host-to-determ.patch     Text File 0001-CLJS-2433-use-JVM-to-deduce-MIME-type-send-files-via.patch     Text File 0002-CLJ-2433-send-fils-via-send-and-close.patch    
Patch: Code

 Description   
$ cat deps.edn
{:deps {org.clojure/clojure {:mvn/version "1.9.0-RC2"}
        org.clojure/clojurescript {:mvn/version "1.9.946"}}
$ touch hello.xml
$ clojure -m cljs.browser.repl &
$ curl localhost:9000/hello.xml
<html><body><h2>Page not found</h2>No page /hello.xml found on this server.</body></html>

Adding an entry to cljs.repl.browser/ext->mime-type superficially fixes that.

1) Currently used MIME type identification is very simplistic and doesn't return correct MIME types for most files. Instead, this should be delegated to the host:

(ns cljs.repl.browser
  (:import [java.nio.file Files Paths]))

(defn get-content-type [path]
  (Files/probeContentType (Paths/get path (into-array String []))))

2) Since both files and sockets are abstractions over bytes, cljs.repl.server/send-and-close should be agnostic to file encoding and just send whatever is in the file. Currently this is handled via cljs.repl.browser/mime-type->encoding.

I will prepare a patch by tomorrow.



 Comments   
Comment by Yegor Timoshenko [ 25/Dec/17 10:16 AM ]

I disagree with this being a minor defect. Currently most files are not served by the built-in HTTP server, which means that it's impossible to develop an application that has files other than HTML/CSS/JS.

Comment by David Nolen [ 26/Dec/17 7:03 AM ]

The builtin webserver is not an important component of ClojureScript. It exists to aid tutorials.

Comment by Yegor Timoshenko [ 26/Dec/17 7:10 AM ]

I like it much more than figwheel because it's simpler, and it seems to be feature-complete other than this bug. Also, this is the first in-browser REPL that comes to mind when using new `clojure` tooling.

Also, previous version of this patch didn't correctly count Content-Length, changed arity of send-and-close function, and didn't work for favicons. I'm attaching a new patch that this time should be complete and cause zero breakage.

New patch is called 0001-CLJS-2433-use-JVM-to-deduce-MIME-type-send-files-via.patch in the attachments above. Link: https://dev.clojure.org/jira/secure/attachment/17586/0001-CLJS-2433-use-JVM-to-deduce-MIME-type-send-files-via.patch

Here's a GitHub link (for code review/explanations): https://github.com/hackberryhike/clojurescript/commit/ea8336da3a779cb5982875d243dc6d40abd0d3ba

Comment by Yegor Timoshenko [ 26/Dec/17 7:18 AM ]

Also, if you don't like something about this patch, do tell me and I'll fix it right away. I'm very interested in getting this merged.

Comment by Nikolas Göbel [ 19/Apr/18 3:22 PM ]

Allow me to make a case for this as well. Although somewhat of an edge case, I spent quite some
time today figuring out why cljs.main -s wouldn't serve my WebAssembly file, when everything else worked perfectly.
Especially considering the great experience provided by the new clj tooling, having to use a separate
server for one-off experiments is somewhat annoying.

Comment by David Nolen [ 19/Apr/18 6:41 PM ]

Can we get a rebased patch?

Comment by Yegor Timoshenko [ 19/Apr/18 8:06 PM ]

Sure, will do by Monday.

Comment by Nikolas Göbel [ 20/Apr/18 4:52 AM ]

Thank you. Please let me know if I can be of assistance.





[CLJS-2467] Small PVs are never chunked Created: 12/Jan/18  Updated: 17/May/18

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

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

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

 Description   

A PersistenVector that has <=32 elements and is seq'ed will return an IndexedSeq. Though IndexedSeq always fails the chunked-seq? check.

This means a:

(def xv (vec (range 32)))
(reduce + (map inc xv))

is about 4x slower than a map over a vector with 33 elements.

Options:
1. Return a ChunkedCons with the "rest" set to nil in PersistentVector.seq()
2. Implement IChunkedSeq for IndexedSeq:

(extend-type IndexedSeq
    IChunkedSeq
    (-chunked-first [x] x)
    (-chunked-rest [x] ())
    IChunkedNext
    (-chunked-next [x] nil)
    IChunk
    (-drop-first [coll]
      (if-some [n (-next coll)]
        n
        (throw (js/Error. "-drop-first of empty chunk")))))

I think option #2 is better since IndexedSeq is used quite a bunch throughout the code base, so the chunking will also kick in for many other code paths.



 Comments   
Comment by A. R [ 12/Jan/18 10:20 AM ]

Note:

This is different from Clojure (which does not consider an IndexedSeq a ChunkedSeq) since we use IndexedSeq a lot more where Clojure often uses a ChunkedSeq. For instance:

(apply (fn [& a] (type a)) [1 2 3 4 8])

will return IndexedSeq in CLJS but ChunkedCons in CLJ.

Since these IndexedSeq's will be passed around wildly in a normal CLJS app it makes sense to extend them as a IChunkedSeq since otherwise all these will never be chunked and get a slow first/next treatment.





[CLJS-575] cljsc.bat emit FileNotFoundException when compile samples in windows Created: 25/Aug/13  Updated: 14/May/18

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

Type: Defect Priority: Minor
Reporter: Park Sang Kyu Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: Compiler, bug, patch
Environment:

in windows 7


Attachments: Text File cljs-575.patch     File cljsc.bat.diff     File cljsc-path.bat    
Patch: Code

 Description   

cljsc.bat emit FileNotFoundException when it compile samples of the ClojureScript project in windows like below.

------------------------------------------------
Exception in thread "main" java.io.FileNotFoundException: Could not locate cljs/closure__init.class
or cljs/closure.clj on classpath:
------------------------------------------------

It is caused by lack of a backslash in the end of path of the system environment variable, %CLOJURESCRIPT_HOME% set by a user.
In the case CLASSPATH is set to "C:\\clojure\clojurescriptsrc\clj;C:\\clojure\clojurescriptsrc\cljs" and this make it impossible for javac to find cljs/clojure.clj file.

So it can be solved by adding a backslash to the path of %CLOJURESCRIPT_HOME%.

I attached the patched file, "cljsc-path.bat"



 Comments   
Comment by David Nolen [ 04/Sep/13 11:04 PM ]

Can we please get a proper git diff thanks (and please send in your CA)! Also would be nice to get Windows users to check this out.

Comment by Park Sang Kyu [ 15/Sep/13 3:16 AM ]

git diff

Comment by David Nolen [ 05/Oct/13 11:55 AM ]

Thank you! Have you sent in your CA? http://clojure.org/contributing

Comment by Park Sang Kyu [ 19/Jun/14 10:24 AM ]

Yes i have sent my CA.

Comment by David Nolen [ 19/Jun/14 10:27 AM ]

Excellent, the patch is not correctly formatted. Can we get a new patch that conforms to http://github.com/clojure/clojurescript/wiki/Patches

Comment by Jeremy R Sellars [ 14/May/18 10:00 PM ]

A properly formatted patch.

When necessary, adds missing path separator at the end of the CLOJURESCRIPT_HOME
environment variable.





[CLJS-2706] Better error messages when missing namespaces contain dashes Created: 26/Mar/18  Updated: 14/May/18  Resolved: 14/May/18

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

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

Attachments: Text File CLJS-2706-2.patch     Text File CLJS-2706-3.patch     Text File CLJS-2706.patch    
Patch: Code

 Description   

ClojureScript could provide better error messages when namespaces with dashes are specified but not found. See CLJS-2705

Reference to equivalent feature in Clojure: https://github.com/clojure/clojure/blob/3d9b356306db77946bdf4809baeb660f94cec846/src/jvm/clojure/lang/RT.java#L463-L464



 Comments   
Comment by Mike Fikes [ 26/Mar/18 6:48 PM ]

Hey Dieter, I think we also need to handle the case when you do a bad require at the REPL, or a ns form specifies a namespace. The revision to the associated warning diagnostic would cover that case. Feel free to combine this with your patch if you'd like.

Also, one comment I'd have on your patch is to perhaps use use the term ClojureScript instead of Clojure.

Comment by Dieter Komendera [ 29/Mar/18 1:38 PM ]

This patch combines Mike's change and my changes and updates the wording as Mike suggested.

Comment by David Nolen [ 29/Mar/18 1:47 PM ]

fixed https://github.com/clojure/clojurescript/commit/487404cf5d70a34a9109f2a2008463a744caa46c





[CLJS-2737] No such file when using fs from ns form Created: 13/Apr/18  Updated: 12/May/18  Resolved: 12/May/18

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

Type: Defect Priority: Major
Reporter: Andrea Richiardi Assignee: Unassigned
Resolution: Not Reproducible Votes: 0
Labels: None


 Description   

With a file like this:

(ns cli-repro.core
  (:require fs))

(enable-console-print!)

(println "ls .:\n" (fs/lstatSync "."))

And a cljsc.edn file like:

{:main cli-repro.core
 :verbose true
 :optimizations :simple
 :target :nodejs}

This fails:

clojure -m "cljs.main" -v -co "cljsc.edn" -c cli-repro.core

With:

Caused by: clojure.lang.ExceptionInfo: No such namespace: fs, could not locate fs.cljs, fs.cljc, or JavaScript source providing "fs" in file /home/arichiardi/tmp/cli-repros/src/cli_repro/core.cljs {:tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4754)
	at clojure.core$ex_info.invoke(core.clj:4754)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:697)
	at cljs.analyzer$error.invoke(analyzer.cljc:693)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:695)
	at cljs.analyzer$error.invoke(analyzer.cljc:693)
	at cljs.analyzer$analyze_deps.invokeStatic(analyzer.cljc:2129)
	at cljs.analyzer$analyze_deps.invoke(analyzer.cljc:2103)
	at cljs.analyzer$ns_side_effects.invokeStatic(analyzer.cljc:3476)
	at cljs.analyzer$ns_side_effects.invoke(analyzer.cljc:3471)
	at cljs.analyzer$analyze_STAR_$fn__2510.invoke(analyzer.cljc:3596)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6762)
	at clojure.core$reduce.invoke(core.clj:6745)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3596)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:3586)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3616)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:3598)
	at cljs.compiler$emit_source.invokeStatic(compiler.cljc:1386)
	at cljs.compiler$emit_source.invoke(compiler.cljc:1365)
	at cljs.compiler$compile_file_STAR_$fn__3672.invoke(compiler.cljc:1467)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1285)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1274)
	at cljs.compiler$compile_file_STAR_.invokeStatic(compiler.cljc:1451)
	at cljs.compiler$compile_file_STAR_.invoke(compiler.cljc:1444)
	at cljs.compiler$compile_file$fn__3702.invoke(compiler.cljc:1547)
	... 43 more

Note that it works with js/require.



 Comments   
Comment by Thomas Heller [ 14/Apr/18 3:04 AM ]

Probably duplicate: https://dev.clojure.org/jira/browse/CLJS-2724

Comment by Andrea Richiardi [ 17/Apr/18 11:38 AM ]

Data point: Juho reported on Slack that it is working for him with `lein`.

Comment by Mike Fikes [ 12/May/18 8:14 AM ]

No longer reproducible on master.





[CLJS-2527] Add iterator-seq to cljs.core Created: 15/Feb/18  Updated: 09/May/18

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: None

Attachments: Text File CLJS-2527.1.patch     Text File cljs-2527.2.patch     Text File CLJS-2527.patch    
Patch: Code and Test

 Description   

It would be great to add iterator-seq which comes standard in Clojure to ClojureScript. While it might be more useful overall in Clojure as a way of dealing with iterable things from Java-land, both Clojure and ClojureScript have there own collections which support iteration which makes it useful.



 Comments   
Comment by Mike Fikes [ 14/Mar/18 7:30 PM ]

Patch no longer applies.

Comment by Thomas Mulvaney [ 15/Mar/18 4:44 AM ]

Thanks Mike, updated patch attached.

Comment by Mike Fikes [ 08/May/18 9:47 AM ]

CLJS-2527.1.patch no longer applies

Comment by Thomas Mulvaney [ 09/May/18 5:49 AM ]

Thanks, new patch attached.





[CLJS-2004] Minor fix for test-simple script Created: 10/Apr/17  Updated: 08/May/18

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

Type: Enhancement Priority: Minor
Reporter: Dejan Josifovic Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: clojurescript, script, test
Environment:

Lubuntu 16.10


Attachments: Text File CLJS-2004.patch     Text File CLJS-2004-rebase-08052018.patch     Text File CLJS-2004-rebase.patch    
Patch: Code

 Description   

On Ubuntu based Linux distributions $[] doesn't work.
Output is: Tested with $[ran+1] out of 4 possible js targets
and should be: Tested with 4 out of 4 possible js targets

As in CLJS-929 (for test script), $(()) will work for ash, dash, bash, and zsh.



 Comments   
Comment by Dejan Josifovic [ 10/Apr/17 2:42 PM ]

Add patch.

Comment by Mike Fikes [ 19/Nov/17 7:32 PM ]

Patch no longer applies; needs re-baseline.

Comment by Dejan Josifovic [ 12/Dec/17 5:33 PM ]

Hi,
Sorry for the late replay.
Rebased patch is uploaded.
Regards.

Comment by Mike Fikes [ 08/May/18 9:48 AM ]

CLJS-2004-rebase.patch no longer applies

Comment by Dejan Josifovic [ 08/May/18 1:03 PM ]

Done.
Cheers.





[CLJS-2624] cljs.main: With temp dir, src attribute /main.js in default index.html Created: 06/Mar/18  Updated: 08/May/18

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

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

{:deps {org.clojure/clojurescript {:git/url "https://github.com/clojure/clojurescript" :sha "7aca40c4b6131b8e08153809a410c06bdfa567ab"}}}


Attachments: Text File CLJS-2624-2.patch     Text File CLJS-2624-3.patch     Text File CLJS-2624-4.patch     Text File CLJS-2624.patch    
Patch: Code

 Description   

With the new feature to use a temp output dir, the script tag has an odd src attribute

<script src="/main.js" type="text/javascript"></script>

Repro:

clj -Srepro -m cljs.main

If, on the other hand you do

clj -Srepro -m cljs.main -d out -r

you get

<script src="out/main.js" type="text/javascript"></script>


 Comments   
Comment by Mike Fikes [ 06/Mar/18 7:32 PM ]

The attached patch simply defaults to "out" if output-dir is not set, but only for the purposes of the rendering call default-index.

Comment by Mike Fikes [ 06/Mar/18 10:08 PM ]

This is actually incorrect to do. If the user copies the index.html that this patch renders, then the REPL no longer works because it no longer points to the main.js.

Comment by Mike Fikes [ 07/Mar/18 6:49 AM ]

The (more complicated) patch 2 adds logic that doesn't use a temp out dir if index.html exists.

Comment by Mike Fikes [ 11/Mar/18 8:14 AM ]

Third patch rebaselines.

Comment by Mike Fikes [ 08/May/18 10:29 AM ]

CLJS-2624-4.patch rebaselines





[CLJS-2724] Native Node modules Node (like "fs") cannot be required Created: 05/Apr/18  Updated: 07/May/18  Resolved: 07/May/18

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

Type: Defect Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Completed Votes: 13
Labels: None

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

 Description   

test.cljs

(require 'fs)
(println (fs/readFileSync "README.md" "utf8"))

command:

clj -A:cljs test.cljs


 Comments   
Comment by Mike Fikes [ 08/Apr/18 5:19 PM ]

I can reproduce this only when running a file, but not when in the REPL.

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
test.cljs
(require 'fs)
(println (fs/readFileSync "deps.edn" "utf8"))

REPL

$ clj -Srepro -m cljs.main -re node
ClojureScript 1.10.238
cljs.user=> (require 'fs)
nil
cljs.user=> (println (fs/readFileSync "deps.edn" "utf8"))
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}

nil
cljs.user=>

Run Directly

$ clj -Srepro -m cljs.main -re node test.cljs
Exception in thread "main" clojure.lang.ExceptionInfo: No such namespace: fs, could not locate fs.cljs, fs.cljc, or JavaScript source providing "fs" at line 1 test.cljs {:file "test.cljs", :line 1, :column 1, :root-source-info {:source-type :fragment, :source-form (require (quote fs))}, :tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4739)
	at clojure.core$ex_info.invoke(core.clj:4739)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:697)
	at cljs.analyzer$error.invoke(analyzer.cljc:693)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:695)
	at cljs.analyzer$error.invoke(analyzer.cljc:693)
	at cljs.analyzer$analyze_deps.invokeStatic(analyzer.cljc:2129)
	at cljs.analyzer$analyze_deps.invoke(analyzer.cljc:2103)
	at cljs.analyzer$ns_side_effects.invokeStatic(analyzer.cljc:3476)
	at cljs.analyzer$ns_side_effects.invoke(analyzer.cljc:3471)
	at cljs.analyzer$analyze_STAR_$fn__2510.invoke(analyzer.cljc:3596)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3596)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:3586)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3616)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:3598)
	at cljs.analyzer$analyze_seq.invokeStatic(analyzer.cljc:3378)
	at cljs.analyzer$analyze_seq.invoke(analyzer.cljc:3355)
	at cljs.analyzer$analyze_form.invokeStatic(analyzer.cljc:3545)
	at cljs.analyzer$analyze_form.invoke(analyzer.cljc:3541)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3595)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:3586)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3616)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:3598)
	at cljs.repl$evaluate_form$fn__6365.invoke(repl.cljc:543)
	at cljs.repl$evaluate_form.invokeStatic(repl.cljc:542)
	at cljs.repl$evaluate_form.invoke(repl.cljc:484)
	at cljs.repl$evaluate_form.invokeStatic(repl.cljc:491)
	at cljs.repl$evaluate_form.invoke(repl.cljc:484)
	at cljs.repl$evaluate_form.invokeStatic(repl.cljc:489)
	at cljs.repl$evaluate_form.invoke(repl.cljc:484)
	at cljs.repl$load_stream.invokeStatic(repl.cljc:575)
	at cljs.repl$load_stream.invoke(repl.cljc:570)
	at cljs.cli$default_main$fn__6799$fn__6800.invoke(cli.clj:348)
	at cljs.cli$default_main$fn__6799.invoke(cli.clj:347)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1285)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1274)
	at cljs.compiler.api$with_core_cljs.invokeStatic(api.clj:50)
	at cljs.compiler.api$with_core_cljs.invoke(api.clj:34)
	at cljs.compiler.api$with_core_cljs.invokeStatic(api.clj:42)
	at cljs.compiler.api$with_core_cljs.invoke(api.clj:34)
	at cljs.cli$default_main.invokeStatic(cli.clj:326)
	at cljs.cli$default_main.invoke(cli.clj:299)
	at cljs.cli$script_opt.invokeStatic(cli.clj:403)
	at cljs.cli$script_opt.invoke(cli.clj:401)
	at cljs.cli$main.invokeStatic(cli.clj:612)
	at cljs.cli$main.doInvoke(cli.clj:601)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
Comment by Mike Fikes [ 05/May/18 6:42 PM ]

The root cause is that in the code path when cljs.main executes a script, it uses the ensure macro, which ends up establishing a compiler environment that isn't set up for Node—set up using (cljs.env/default-compiler-env). If an opts map is passed to cljs.env/default-compiler-env which contains :target :nodejs entry, then the desired native Node modules, in cljs.js-deps/native-node-modules will be included.

The fix is to instead of using ensure, either use with-compiler-env or to just bind *compiler* to one set up using the right opts. The attached patch looks much larger than it really is, owing to a lot of whitespace change produced by removing an outermost ensure wrapper. It removes the ensure and simply adds env/*compiler* (env/default-compiler-env opts) to the binding list.

I checked that the patch also works in the case of using cljs.main to compile code using 'fs. A CLI test is added ensuring that you can use native modules in -e forms, which is roughly analogous to what happens when running a script. (I also checked tat this new CLI test fails if you don't include the production code change.)

Comment by David Nolen [ 07/May/18 3:47 PM ]

fixed https://github.com/clojure/clojurescript/commit/78753d376d5bfe9afd1dbb98eea15fd5bd312255





[CLJS-2702] Accomodate new Closure Library dependency loading strategy Created: 24/Mar/18  Updated: 07/May/18  Resolved: 07/May/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 1
Labels: closure-library

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

 Description   

goog.dependencies_ is now evidently gone in newer versions of Closure Library.

See https://github.com/google/closure-library/commit/aa92ba3c3cf3861baec980ae2c05d9ae265d9841#diff-c359099ba4bc09bc2864536c49356d52L875

To see a consequence of this, first set up to use Closure Library head:

$ script/clean
$ script/bootstrap --closure-library-head

then try to start the Node REPL:

$ script/noderepljs
Exception in thread "main" clojure.lang.ExceptionInfo: repl:2
return CLOSURE_IMPORT_SCRIPT((goog.dependencies_.nameToPath[name]));
                                                 ^

TypeError: Cannot read property 'nameToPath' of undefined


 Comments   
Comment by Mike Fikes [ 05/May/18 12:54 PM ]

The changes in the patch accomodate the updates in Closure Library while preserving the ability to operate with the current Closure Library dep. (It doesn't actually upgrade Closure Library; this can be done separately.)

The primary change is to accomodate the relocation of dependency management logic to be under goog.debugLoader_. (The existence of this field is used in many places to conditionally enable the new behavior.) The patch doesn't attempt to move away from private API; it simply makes it so we can adopt the new locations.

The browser REPL presented the most challenging case, but leveraging CLOSURE_IMPORT_SCRIPT allows us to hook in our existing custom writeScriptTag_ logic.

Closure Library employs some ES6 code in goog/loader/activemodulemanager.js, so one of the unit tests was revised to accomodate this aspect.

Comment by David Nolen [ 07/May/18 3:46 PM ]

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





[CLJS-2741] Function invoke errors report arity off by 1 Created: 21/Apr/18  Updated: 07/May/18  Resolved: 07/May/18

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

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: error-reporting, errormsgs, regression

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

 Description   

((fn ([x]) ([x y]))) results in Error: Invalid arity: -1
((fn ([x]) ([x y])) 1 2 3) results in Error: Invalid arity: 2

This is a regression caused by CLJS-1519.



 Comments   
Comment by David Nolen [ 07/May/18 3:40 PM ]

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





[CLJS-2745] Add GraalVM to the set of JavaScript engines we can test against Created: 28/Apr/18  Updated: 07/May/18  Resolved: 07/May/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: test

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

 Description   

Like the others at https://clojurescript.org/community/running-tests, add a new GRAALVM_HOME, and add this new engine to the test suite. For the Travis build, have it download the binaries for Linux from here https://github.com/oracle/graal/releases



 Comments   
Comment by David Nolen [ 07/May/18 3:38 PM ]

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





[CLJS-2739] Optimize node_modules indexing Created: 17/Apr/18  Updated: 07/May/18  Resolved: 07/May/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Completed Votes: 5
Labels: npm-deps

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

 Description   

Indexing node_modules can take quite a while. As an example, with the node_modules directory that is set up for React Native projects, on a 2012 Mac Pro, this can take about 45 seconds. This is long enough where, if node_modules isn't actually being used for ClojureScript, using :npm-deps false is highly motivated.

If there was a way to make this closer to instantaneous (perhaps via caching or other clever approaches), then this would benefit all users.



 Comments   
Comment by Juho Teperi [ 17/Apr/18 10:38 AM ]

Based on Mike's test this is mostly caused by index-node-modules-dir, which reads the node modules dir tree using JVM: https://gist.github.com/mfikes/c99cfac7b9f5ae48fc9644bbde492a3c

Comment by Mike Fikes [ 06/May/18 5:06 PM ]

For one of my projects the attached patch drops the time spent in index-node-modules-dir from 30 seconds to 5 seconds.

Comment by David Nolen [ 07/May/18 3:29 PM ]

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





[CLJS-2738] Can't use aws-amplify or aws-sdk with npm-deps Created: 15/Apr/18  Updated: 05/May/18

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

Type: Defect Priority: Major
Reporter: Quang Van Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: npm-deps


 Description   

If I put aws-amplify in :npm-deps it seems to require aws-sdk, but when I put aws-sdk in there, it outputs this error:

Compiling build :dev to "resources/public/js/main.js" from ["src"]...
events.js:182
      throw er; // Unhandled 'error' event
      ^

Error: module not found: "fs" from file /home/quang/dev/org-re-frame/node_modules/aws-amplify/node_modules/aws-sdk/lib/util.js
    at onresolve (/home/quang/dev/org-re-frame/node_modules/@cljs-oss/module-deps/index.js:181:30)
    at onResolve (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/Resolver.js:70:11)
    at innerCallback (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/Resolver.js:143:22)
    at callbackWrapper (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/createInnerCallback.js:10:21)
    at next (/home/quang/dev/org-re-frame/node_modules/tapable/lib/Tapable.js:249:35)
    at innerCallback (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/Resolver.js:143:22)
    at callbackWrapper (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/createInnerCallback.js:10:21)
    at next (/home/quang/dev/org-re-frame/node_modules/tapable/lib/Tapable.js:249:35)
    at resolver.doResolve.createInnerCallback (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:41:24)
    at callbackWrapper (/home/quang/dev/org-re-frame/node_modules/enhanced-resolve/lib/createInnerCallback.js:10:21)


 Comments   
Comment by Jeffrey Stanton [ 26/Apr/18 2:51 PM ]

I've also run into the same issue. Here's a simple repro:

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
src/foo.cljs
(ns foo (:require ["aws-sdk" :as sdk]))
(defn -main [] (println "hello world"))

then run:

$ clj -m cljs.main -co '{:install-deps true, :npm-deps {:aws-sdk "2.229.1"}}' -m foo
...
Error: module not found: "fs" from file /Users/jeff/repro/node_modules/aws-sdk/lib/util.js
    at onresolve (/Users/jeff/repro/node_modules/@cljs-oss/module-deps/index.js:181:30)
    at onResolve (/Users/jeff/repro/node_modules/enhanced-resolve/lib/Resolver.js:70:11)
    at innerCallback (/Users/jeff/repro/node_modules/enhanced-resolve/lib/Resolver.js:143:22)
    at callbackWrapper (/Users/jeff/repro/node_modules/enhanced-resolve/lib/createInnerCallback.js:10:21)
    ...
Comment by Mike Fikes [ 05/May/18 7:35 PM ]

The big picture is not completely clear to me for this one, but it appears that the NPM version of the library is not intended to be used directly from the browser runtime, and instead you need to build it so that it is packaged for the browser.

The root problem is that the code is attempting to use Node's fs code, but from the browser.

You can see that the code can be compiled and executed if you target Node: If you modify Jeffrey's minimal repro to add

(set! *main-cli-fn* -main)

to the bottom of src/foo.cljs then things will compile and execute in Node:

$ clj -m cljs.main -co '{:install-deps true, :npm-deps {:aws-sdk "2.229.1"}}' -O simple -o main.js -t node -c foo
WARNING: foo is a single segment namespace at line 1 /private/tmp/aws/src/foo.cljs
$ node main.js
hello world

For the browser case, if you look at the code in node_modules/aws-sdk/lib/util.js you can see that it has conditional branches for browser use, but I suspect that this is intended to be used as described here https://github.com/aws/aws-sdk-js#in-the-browser but if you really want to use the code directly from its NPM dependency, you have to use that NPM dependency to build the JavaScript intended to be used in the browser as detailed here: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/building-sdk-for-browsers.html

If this can be confirmed, then this issue can be resolved as a non-issue, and it is just a matter of correct use of the library.

Comment by David Whittington [ 05/May/18 8:23 PM ]

I can confirm that it works in the browser with the AWS recommended browser build process. I was hoping it would also work as a node dep, but I think you're probably right that it's just not intended to be used that way.





[CLJS-1965] letfn collisions across namespaces Created: 02/Mar/17  Updated: 02/May/18

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

Type: Defect Priority: Minor
Reporter: Jeremy R Sellars Assignee: David Nolen
Resolution: Unresolved Votes: 3
Labels: None
Environment:

Affects 1.9.495 and earlier. Probably only affects browsers (not nodejs).


Attachments: Text File CLJS-1965-failing-tests.patch     Text File cljs-1965_wrap_letfn_statements.patch     Text File CLJS-1965-Wrap-top-level-letfn-to-avoid-collisions.patch    
Patch: Code

 Description   

If you `letfn` a fn with the same name in two namespaces, the wrong fn is used.

one.cljs
(ns hello-world.one)

(letfn [(answer [] "1")]
  (defn get-answer []
    (answer)))
two.cljs
(ns hello-world.two)

(letfn [(answer [] "2")]
  (defn get-answer []
    (answer)))
core.cljs
(ns hello-world.core
  (:require [hello-world.one]
            [hello-world.two]))

(println "one =>" (hello-world.one/get-answer))  ; one => 1
(println "two =>" (hello-world.two/get-answer))  ; two => 1      WHAT?!?

This issue seems to exist both on top-level `letfn`s and non-top-level `(let [] (letfn [...]))`.



 Comments   
Comment by Jeremy R Sellars [ 02/Mar/17 4:21 PM ]

This patch wraps `letfn` :expr and :statement forms in a function declaration (formerly, only :expr forms were wrapped).

I only did minimal testing. It fixes the code from the description.

Note: This is my first crack at the compiler and it is entirely possible I have not understood the entire problem.

Comment by Mike Fikes [ 16/Jun/17 10:54 AM ]

Confirmed that this fixes things downstream in self-hosted ClojureScript (Planck):

Without the patch:

cljs.user=> (require 'hello-world.core)
one => 2
two => 2
nil

With the patch:

cljs.user=> (require 'hello-world.core)
one => 1
two => 2
nil
Comment by daniel sutton [ 29/Dec/17 3:18 PM ]

This doesn't require different namespaces. The bug is that `let-fn` is putting its binding as a global variable.

And easy reproduction is
1. `lein new mies letfn-bug`,
2. update cljs version to `[org.clojure/clojurescript "1.9.946"]`
3. and then

(ns letfn-bug.core
  (:require [clojure.browser.repl :as repl]))

(enable-console-print!)

(letfn [(non-unique-name [] 4)]
  (defn f1 [] (non-unique-name)))

(letfn [(non-unique-name [] 5)]
  (defn f2 [] (non-unique-name)))

(println "should be 4-> " (f1))
(println "should be 5-> " (f2))

then `scripts/repl`.

results in:

cljs.user=> (load-file "letfn_bug/core.cljs")
should be 4->  5
should be 5->  5
nil
cljs.user=>

With the generated js:

// Compiled by ClojureScript 1.9.946 {}
goog.provide('letfn_bug.core');
goog.require('cljs.core');
goog.require('clojure.browser.repl');
cljs.core.enable_console_print_BANG_.call(null);
var non_unique_name = (function letfn_bug$core$non_unique_name(){
return (4);
});
letfn_bug.core.f1 = (function letfn_bug$core$f1(){
return non_unique_name.call(null);
});
var non_unique_name = (function letfn_bug$core$non_unique_name(){
return (5);
});
letfn_bug.core.f2 = (function letfn_bug$core$f2(){
return non_unique_name.call(null);
});
cljs.core.println.call(null,"should be 4-> ",letfn_bug.core.f1.call(null));
cljs.core.println.call(null,"should be 5-> ",letfn_bug.core.f2.call(null));
Comment by David Nolen [ 05/Jan/18 10:42 AM ]

Quick review of the patch, instead of always wrapping in a statement context it might be better if we only did it at the top-level where this is actually a problem.

Comment by George Lipov [ 01/May/18 2:27 PM ]

I'd just like to chime in and suggest that the priority on this be raised. A compiler breaking scope like this is certainly not a minor issue.

Comment by Jeremy R Sellars [ 02/May/18 10:06 AM ]

This patch is like the first, but only function-wraps statement letfn forms that are outside a fn-scope. (CLJS-1965-Wrap-top-level-letfn-to-avoid-collisions.patch)





[CLJS-2347] NPE on :infer-externs true Created: 03/Sep/17  Updated: 02/May/18

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

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


 Description   

When :infer-externs is true in 1.9.908, an NPE will result from the Closure compiler. Also reported here with a stacktrace:

https://github.com/google/closure-compiler/issues/2629



 Comments   
Comment by Juho Teperi [ 08/Sep/17 9:00 AM ]

Well, this is interesting. I haven't been able to reproduce this without Boot-cljs completely, but I can reproduce this with Cljs by manually providing extern with single line: `var COMPILED;`. For some reason, inferred extern with Boot-cljs includes this line, but not when calling compiler directly.
`

Comment by Dieter Komendera [ 02/May/18 2:00 AM ]

The above linked closure-compiler issue has been closed. https://github.com/clojure/clojurescript/commit/30bc7c2ef251d74c2ab398c2a1461984f9c80469 might have fixed this issue.





[CLJS-2747] Indexing of node modules should not be done when :npm-deps is nil Created: 01/May/18  Updated: 01/May/18  Resolved: 01/May/18

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

Type: Defect Priority: Major
Reporter: Andrea Richiardi Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

While debugging a problem in lumo, I have run against a core bug I think.

So basically I think that the check:

(if (not (false? npm-deps)))
  (index-node-modules-dir))

should be extended, if I understand correctly, to:

(when (not (or (nil? npm-deps) (false? npm-deps)))
  (index-node-modules-dir))

or we will index on nil which is probably not necessary.

I can take care of this simple patch if this is confirmed to be the right behavior and I understand things correctly.



 Comments   
Comment by Andrea Richiardi [ 01/May/18 8:24 PM ]

After conversation with Antonio he kindly explained me that we want to index when :npm-deps is nil actually. The error I am seeing in lumo is because we throw where we should not. Sorry for the noise, closing this.





[CLJS-2622] Add support for package tarballs in :npm-deps Created: 06/Mar/18  Updated: 30/Apr/18

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

Type: Enhancement Priority: Major
Reporter: Jannis Pohlmann Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: npm-deps

Attachments: Text File CLJS-2622.patch    

 Description   

NPM supports installing packages from tarballs via {npm install /path/to/foo.tgz}. This can be useful for trying a local (modified) version of a package, or generally any unpublished and/or private JS project; all that's needed is a {package.json} and a {.js} file and {npm pack} can generate a tarball.

It would be nice if ClojureScript would support this as well, through {:npm-deps}.

Proposed syntax:

{:npm-deps {"/path/to/tarball.tgz" "0.1.0"
            "/path/to/bar.tgz" ""}}

The version isn't needed with tarballs, so it could be anything.

I have the code for this working but I still want to add a test before I submit a patch.



 Comments   
Comment by Jannis Pohlmann [ 07/Mar/18 7:18 AM ]

This patch implements the feature and adds tests for indexing and building with a tarball dependency.

Comment by Thomas Heller [ 30/Apr/18 2:53 PM ]

What benefit does this provide over just running npm install ./some.tgz?

I don't think this is a good idea.





[CLJS-2341] Speed up js->clj on objs using forEach and transient volatile Created: 30/Aug/17  Updated: 30/Apr/18

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

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 9
Labels: performance

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

 Description   

It is possible to speed up js->clj on JavaScript objects by revising the implementation to employ goog.object/forEach, accumulating by bashing on a transient volatile map.

The speedups range from 1.5 to 2.1 over the current implementation.

Note: The current implementation uses js-keys. The optimization in CLJS-2340 could help js->clj, but it doesn't appear to provide much speedup in itself (perhaps 1.1?) compared to the change in implementation described above.



 Comments   
Comment by Mike Fikes [ 30/Aug/17 9:19 AM ]
Speedup Summary:

        Engine  small, medium, with sub-object
            V8: 1.62, 1.50, 1.13
  SpiderMonkey: 1.91, 1.74, 1.59
JavaScriptCore: 1.67, 1.74, 2.10
       Nashorn: 1.54, 2.13, 1.51
    ChakraCore: 1.71, 2.10, 1.95


Before:

Benchmarking with V8
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 55 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 63 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 93 msecs

Benchmarking with SpiderMonkey
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 155 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 87 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 94 msecs

Benchmarking with JavaScriptCore
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 45 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 33 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 42 msecs

Benchmarking with Nashorn
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 1123 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 1195 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 773 msecs

Benchmarking with ChakraCore
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 65 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 44 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 78 msecs


After:

Benchmarking with V8
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 34 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 42 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 82 msecs

Benchmarking with SpiderMonkey
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 81 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 50 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 59 msecs

Benchmarking with JavaScriptCore
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 27 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 19 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 20 msecs

Benchmarking with Nashorn
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 728 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 561 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 513 msecs

Benchmarking with ChakraCore
[obj (js-obj "a" 1 "b" 2)], (js->clj obj), 1000 runs, 38 msecs
[obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6)], (js->clj obj), 1000 runs, 21 msecs
[sub-obj (js-obj "g" 7 "h" 8 "i" 9 "j" 10) obj (js-obj "a" 1 "b" 2 "c" 3 "d" 4 "e" 5 "f" 6 "s" sub-obj)], (js->clj obj), 1000 runs, 40 msecs
Comment by Thomas Mulvaney [ 30/Apr/18 7:38 AM ]

Hi Mike. I don't think the volatile is required, see for example: PersistentHashMap.createWithCheck - the transient can be mutated in place. Although quite often in core.cljs it does seem to be passed as an arg in recursive calls such as in most of the .-fromArray methods of collections. Removing the volatile will likely make even more of an improvement.

Comment by Francis Avila [ 30/Apr/18 10:09 AM ]

To clarify what Thomas said: It's not part of the contract of transients that they can be mutated in place--you are supposed to use the return value of assoc! etc as you have done.

If you bash in place, you will get this:

(let [t (transient {})]
  (dotimes [i 32]
    (assoc! t i i))
  (persistent! t))
=> {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7} ;; broken!

(t is initially a transient array-map; assoc! returns a transient hash-map after 8 items, which you never see because of the in-place bashing.)

So your patch is good in this respect: you should definitely not bash transients in place!

However, particular transient types may be implemented in such a way that the only thing that their edit functions (assoc! dissoc! etc) ever return is the same (identical) object passed in to them. This is true for TransientHashMap's assoc!, which is why PersistentHashMap.createWithCheck is not broken. (It's liable to be brittle though if its implementation ever changes--I hope createWithCheck has good test coverage.)

Comment by Mike Fikes [ 30/Apr/18 10:13 AM ]

So, TL;DR is that, with some risk of brittleness, we could bash in place and potentially get more perf.

Comment by Francis Avila [ 30/Apr/18 10:35 AM ]

No, wrong TLDR: in this particular patch you cannot bash (transient {}) in place, because this starts out as an array-map and returns a transient hash-map once assoc! would return a map with a count greater than 8.

PersistentHashMap.createWithCheck (the example Thomas cited) can bash because it is written very carefully and knows all the types and their implementations.

If you only use hash-maps e.g. with (transient (hash-map)) you can bash in place, but then you won't have array-map for small maps.

(Really, don't bash transients in place.)

Comment by Thomas Mulvaney [ 30/Apr/18 11:00 AM ]

Francis is right, ignore me. Bashing things in place that don't change type works but possibly might break if implementations change. Docs clearly say its a bad idea - just because I've seen it done doesn't make it ok!





[CLJS-2744] Duplicate cljs-1883-test-foreign-libs-use-relative-path Created: 27/Apr/18  Updated: 27/Apr/18

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

Type: Defect Priority: Trivial
Reporter: Andrea Richiardi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In the tests there are two cljs-1883-test-foreign-libs-use-relative-path. Better to rename it.






[CLJS-2376] Add support for ES6 default imports/exports Created: 02/Oct/17  Updated: 26/Apr/18

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

Type: Enhancement Priority: Minor
Reporter: Thomas Heller Assignee: Juho Teperi
Resolution: Unresolved Votes: 11
Labels: npm-deps

Attachments: Text File CLJS-2376-1.patch    

 Description   

ES6 has special syntax for using "default" imports and there is currently no equivalent for CLJS when using imported ES6 code.

import * as name from "module-name";
(:require ["module-name" :as name])

import { export } from "module-name";
(:require ["module-name" :refer (export)])

import { export as alias } from "module-name";
(:require ["module-name" :refer (export) :rename {export alias}])

import defaultExport from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
;; no easy access to defaultExport

I'm proposing to add a :default to the ns :require.

(:require ["module-name" :as mod :default foo])

This makes it much more convenient to use rewritten ES6 code from CLJS. If "module-name" has a default export you currently have to write mod/default everywhere since they is no easy way to alias the default.

(:require ["material-ui/RaisedButton" :as RaisedButton])
;; :as is incorrect and the user must now use
RaisedButton/default

(:require ["material-ui/RaisedButton" :default RaisedButton])
;; would allow direct use of
RaisedButton

Internally the Closure compiler (and ES6 code rewritten by babel) will rewrite default exports to a .default property, so :default really is just a convenient way to access it.

The long version that already works is

(:require ["material-ui/RaisedButton" :refer (default) :rename {default RaisedButton}])

When ES6 becomes more widespread we should have convenient way to correctly refer to "default" exports.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import



 Comments   
Comment by Juho Teperi [ 10/Jan/18 2:25 PM ]

First take on the implementation. This implementation rewrites :default name to {{:refer [default] :rename {default name}}} at the lowest level (parse-require-spec), so I think other functions don't need to be changed.

I didn't update the require spec validation errors yet.

Comment by David Nolen [ 12/Feb/18 6:25 AM ]

It seems to me the most desirable syntax for ES6 default imports is the following:

(:require ["material-ui/RaisedButton" :refer [RaisedButton]])

I don't see why we couldn't just make this work?

Comment by Thomas Heller [ 12/Feb/18 6:55 AM ]

I don't understand that suggestion. The default export has no name, the .default property is only used in interop by transpilers. In actual JS a live reference is used. How would you map RaisedButton back to default?

["material-ui/RaisedButton" :default foo] would be valid. The JS module may also actually have an `export { RaisedButton }` in addition to `export default ...`, which would lead to a conflict if you "guess" the wrong name. Default exports are not aliases for the module itself, that is separate.

I made a reference translation table [1] and adding the :default alias is the only way to reliably map all ES6 import/export features. I don't see a way to make :refer work that would not be totally non-intuitive and unreliable.

import defaultExport, * as name from "module-name";

[1] https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages

Comment by David Nolen [ 12/Feb/18 8:55 AM ]

Let's leave rhetoric out of this discussion please and focus on the technical bits. I just don't want to include another directive in the ns form and I would prefer an approach that avoids that. From my point of view there has not been enough exploration of that alternative.

This ticket is mostly about convenience, and I think we need to stew on this one for a bit longer before deciding on anything.

Comment by jcr [ 24/Mar/18 6:45 AM ]

Is there a reason we can't use metadata to deal with it? I.e.

(:require ["material-ui/RaisedButton" :refer [^:default RaisedButton]])
(:require ["module-name" :as mod :refer [^:default foo])
(:require ["module-name" :refer [^:default foo, bar, baz])

This doesn't require additional ns directives and doesn't cause any ambiguities either.

Since this wasn't used for macros (i.e. we have :require-macros instead of plain :require + ^:macros or :refer [^:macro foo]), I assume there may be some nuances I am not aware of that prevent implementing it. Are there any?

Comment by Thomas Heller [ 26/Apr/18 5:49 PM ]

The ^:default hint seems far more complicated to me from an implementation standpoint.

There is no equivalent for default import/export in Java/JVM and Clojure. There is also no equivalent in CommonJS even. It is strictly about ES6. Therefore bolting it onto "other" methods seems incorrect to me.

The reason it should be separate IMHO is that using the .default property is not strictly correct and the fact that it exists at all is purely for compatibility reasons with CommonJS. In strict ES6 they don't exist as part of the "Object" created by :as.

;; a.js
export let a = 1;
export let b = 2;
export default 3;

;; b.js
import x, * as y from "./a.js"

// these exist
y.a
y.b
// this is NOT valid in ES6 and does not exist
y.default
// instead x must be used
x

We certainly rely on the .default property existing for the time being given that CLJS does not emit ES6. webpack already changed how the default exports are handled however and I do expect the Closure Compiler to do something similar in the future.

Comment by Thomas Heller [ 26/Apr/18 6:06 PM ]

Turns out I'm actually wrong. Re-read the spec and .default is actually defined as a getter, so it is accessible. Nevermind my previous post then.

Doesn't change my opinion about the usefulness of :default as a simpler aliasing method though.





[CLJS-2424] Improve compiler munge performance Nr 2 Created: 28/Nov/17  Updated: 26/Apr/18

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

Type: Enhancement Priority: Minor
Reporter: A. R Assignee: David Nolen
Resolution: Unresolved Votes: 4
Labels: performance

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

 Description   

This is similar to CLJS-2065 and further improves the performance by avoiding reduce and using a key iterator instead.

Results for a large CLJS project with lots of namespaces are:

  • Initial compile (cold) Old: 11.4s New: 11.2s
  • First full recompile: Old: 6.8s New: 5.9s
  • After a few full recompiler (warmed up JVM): Old: ~6.1s New: 5.1s

lein count:

Ext Files Lines of Code Nodes
cljs 138 23388 424745


 Comments   
Comment by David Nolen [ 22/Dec/17 2:24 PM ]

No difference for compiling ClojureScript tests, I will give a try with something else.

Comment by A. R [ 26/Apr/18 5:23 AM ]

Kind of related: CLJS-2461
Better approach would be to re-implement this idea: https://github.com/clojure/clojurescript/commit/1c71ab3bff27dc4a099b06e122ec3fdf5a2a8ba8

Close this issue?





[CLJS-2677] Better handling of npm-deps via REPL require when output-dir not specified Created: 20/Mar/18  Updated: 25/Apr/18

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

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: npm-deps
Environment:

{:deps {org.clojure/clojurescript {:mvn/version "1.10.217"}}}



 Description   

I'm speculating that the following doesn't work because Closure is not involved when requiring at the REPL.

co.edn
{:output-dir "out"
 :output-to "out/main.js"
 :optimizations :none
 :install-deps true
 :npm-deps {:react "15.6.1"
            :react-dom "15.6.1"}}
src/example/core.cljs
(ns example.core
  (:require [react :refer [createElement]]
            ["react-dom/server" :as ReactDOMServer :refer [renderToString]]))

(js/console.log (renderToString (createElement "div" nil "Hello World!")))

This works fine:

clj -m cljs.main -co co.edn -c example.core -r

logging this in the browser console

[Log] <div data-reactroot="" data-reactid="1" data-react-checksum="1309021079">Hello World!</div> (core.js, line 6)

But if instead you start off fresh (without out, node_modules, package.json and package-lock.json) and do

clj -m cljs.main -co co.edn -r

followed by this in the REPL:

(require 'example.core)

No errors are shown in the REPL console, but the JavaScript console shows lots of errors.

I think to satisfy this ticket this could either be made to "just work" somehow, or perhaps instead the problem could be detected and an ex-info thrown letting the user know that things won't work this way.

Here are the errors logged:

[Error] ReferenceError: Can't find variable: process
	Global Code (warning.js:4)
[Error] ReferenceError: Can't find variable: process
	Global Code (canDefineProperty.js:2:170)
[Error] ReferenceError: Can't find variable: process
	Global Code (emptyObject.js:2:153)
[Error] ReferenceError: Can't find variable: process
	Global Code (invariant.js:4:192)
[Error] ReferenceError: Can't find variable: process
	Global Code (lowPriorityWarning.js:3)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactBaseClasses.js:16)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactPropTypeLocationNames.js:2:185)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactDOMFactories.js:5)
[Error] ReferenceError: Can't find variable: process
	Global Code (checkPropTypes.js:10)
[Error] ReferenceError: Can't find variable: process
	createChainableTypeChecker (factoryWithTypeCheckers.js:12:305)
	createPrimitiveTypeChecker (factoryWithTypeCheckers.js:17:102)
	(anonymous function) (factoryWithTypeCheckers.js:10:535)
	(anonymous function) (factory.js:3:441)
	Global Code (ReactPropTypes.js:5:149)
[Error] ReferenceError: Can't find variable: process
	Global Code (factory.js:34:317)
[Error] ReferenceError: Can't find variable: process
	Global Code (React.js:18)
[Error] ReferenceError: Can't find variable: process
	Global Code (EventPluginRegistry.js:16:218)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactErrorUtils.js:5)
[Error] ReferenceError: Can't find variable: process
	Global Code (EventPluginUtils.js:12)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$EventPluginRegistry["default"].injectEventPluginOrder')
	Global Code (EventPluginHub.js:16:199)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$EventPluginHub["default"].getListener')
	Global Code (EventPropagators.js:9:167)
[Error] ReferenceError: Can't find variable: process
	Global Code (SyntheticEvent.js:18)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticEvent["default"].augmentClass...')
	Global Code (SyntheticCompositionEvent.js:4:393)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticEvent["default"].augmentClass...')
	Global Code (SyntheticInputEvent.js:4:203)
[Error] ReferenceError: Can't find variable: process
	Global Code (DOMProperty.js:14:471)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$DOMProperty["default"].ID_ATTRIBUTE_NAME')
	Global Code (ReactDOMComponentTree.js:7:516)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactInvalidSetStateWarningHook.js:4)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactInstrumentation.js:4)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticEvent["default"].augmentClass...')
	Global Code (SyntheticUIEvent.js:7:93)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticUIEvent["default"].augmentClass...')
	Global Code (SyntheticMouseEvent.js:9:95)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$DOMProperty["default"].injection')
	Global Code (HTMLDOMPropertyConfig.js:3:425)
[Error] ReferenceError: Can't find variable: process
	Global Code (DOMChildrenOperations.js:21)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$DOMChildrenOperations["default"].dangerouslyReplaceNodeWithMarkup')
	Global Code (ReactComponentBrowserEnvironment.js:5:349)
[Error] ReferenceError: Can't find variable: process
	Global Code (CSSPropertyOperations.js:17)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$DOMProperty["default"].ATTRIBUTE_NAME_START_CHAR')
	Global Code (DOMPropertyOperations.js:9:200)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react$lib$React["default"].isValidElement')
	Global Code (LinkedValueUtils.js:9:533)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactPropTypeLocationNames.js:2:193)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactCompositeComponent.js:21:366)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactMultiChild.js:21)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactServerRenderingTransaction.js:10:126)
[Error] ReferenceError: Can't find variable: process
	Global Code (validateDOMNesting.js:7)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$EventPluginHub["default"].deleteListener')
	Global Code (ReactDOMComponent.js:42:171)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$DOMProperty["default"].injection')
	Global Code (ReactInjection.js:13:279)
[Error] ReferenceError: Can't find variable: process
	Global Code (ReactReconcileTransaction.js:18)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticEvent["default"].augmentClass...')
	Global Code (SyntheticAnimationEvent.js:4:256)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticEvent["default"].augmentClass...')
	Global Code (SyntheticClipboardEvent.js:4:303)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticUIEvent["default"].augmentClass...')
	Global Code (SyntheticFocusEvent.js:4:214)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticUIEvent["default"].augmentClass...')
	Global Code (SyntheticKeyboardEvent.js:10:95)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticMouseEvent["default"].augmentClass...')
	Global Code (SyntheticDragEvent.js:4:214)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticUIEvent["default"].augmentClass...')
	Global Code (SyntheticTouchEvent.js:6:95)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticEvent["default"].augmentClass...')
	Global Code (SyntheticTransitionEvent.js:4:257)
[Error] TypeError: undefined is not a function (near '...module$private$tmp$island$node_modules$react_dom$lib$SyntheticMouseEvent["default"].augmentClass...')
	Global Code (SyntheticWheelEvent.js:5:98)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$lib$ReactInjection["default"].EventEmitter')
	inject (ReactDefaultInjection.js:22:383)
	Global Code (ReactDOMServer.js:6:257)
[Error] TypeError: undefined is not an object (evaluating 'module$private$tmp$island$node_modules$react_dom$server["default"].renderToString')
	Global Code (core.js:6)


 Comments   
Comment by David Nolen [ 20/Mar/18 9:59 AM ]

You must set :output-dir if you intend to use :npm-deps for now. If we somehow figure out a way to make this work, it also needs to work with Node.js if you do not supply :output-dir.





[CLJS-2626] Assess JavaWebSocket Created: 07/Mar/18  Updated: 25/Apr/18

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

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

Attachments: Text File CLJS-2626.patch    

 Description   

We would like a more robust standard browser based REPL. A WebSocket implementation would be a significant step in that direction. We should assess https://github.com/TooTallNate/Java-WebSocket, it has few dependencies and appears well maintained.



 Comments   
Comment by John Newman [ 17/Mar/18 9:44 AM ]

Working on a patch for this.

Some work has been completed to help us assess TooTallNate/Java-WebSocket. Here is a simple chat server:

https://gist.github.com/johnmn3/a845f2bf67ad877d957bccd7f9cefe8c

Here is a very simple implementation of Java-WebSocket in Weasel:

https://github.com/johnmn3/weasel/commit/e5eb062dca3dbf623ce1c683443f2a0b3768f749

I will be working with @bhauman on this patch. I'm available on slack for anyone interested in discussing design considerations but feel free to comment here with recommendations or questions.

Comment by John Newman [ 25/Apr/18 10:12 AM ]

WIP snapshot of JavaWebSocket assessment





[CLJS-2408] js->clj does not work on objects with null prototype Created: 21/Nov/17  Updated: 25/Apr/18

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

Type: Defect Priority: Major
Reporter: Kurt Harriger Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Version: 1.9.946
Follow up from issue CLJS-1998

cljs.user=> (js->clj #js {})
{}

cljs.user=> (js->clj (.create js/Object nil))
#object[Object]

cljs.user=> (keys (js->clj (.create js/Object nil)))
org.mozilla.javascript.EcmaError: TypeError: Cannot find default value for object. (.cljs_rhino_repl/goog/../.cljs_rhino_repl/cljs/core.js#9915)
	 (.cljs_rhino_repl/cljs/core.cljs:2930:10)
	 cljs$core$seq (.cljs_rhino_repl/cljs/core.cljs:1212:13)
	 cljs$core$keys (.cljs_rhino_repl/cljs/core.cljs:8648:3)
	 (NO_SOURCE_FILE <cljs repl>:1:0)
	 (NO_SOURCE_FILE <cljs repl>:1:0)


 Comments   
Comment by Kurt Harriger [ 21/Nov/17 8:44 PM ]

For more context the source of the object with null prototype is generated in a third party library I am using here https://github.com/ProseMirror/prosemirror-model/blob/cdded3d/src/schema.js#L13

Comment by Kurt Harriger [ 21/Mar/18 7:47 PM ]

```
(def a (.create js/Object null)) => #'cljs.user/a
(type a) => nil
```

The implementation of js->clj explicitly checks for type js/Object.

```
(defn js->clj
"Recursively transforms JavaScript arrays into ClojureScript
vectors, and JavaScript objects into ClojureScript maps. With
option ':keywordize-keys true' will convert object fields from
strings to keywords."
([x] (js->clj x :keywordize-keys false))
([x & opts]
(let [{:keys [keywordize-keys]} opts
keyfn (if keywordize-keys keyword str)
f (fn thisfn [x]
(cond
(satisfies? IEncodeClojure x)
(js>clj x (apply array-map opts))

(seq? x)
(doall (map thisfn x))

(coll? x)
(into (empty x) (map thisfn x))

(array? x)
(vec (map thisfn x))

(identical? (type x) js/Object)
(into {} (for [k (js-keys x)]
[(keyfn k) (thisfn (unchecked-get x k))]))

:else x))
```

I think perhaps this last test should be changed to `(or (nil? (type a)) (identical? (type x) js/Object))` because the only way to create an object with a null prototype is explicitly and they do so because they are intended to be used as associative objects. (http://adripofjavascript.com/blog/drips/creating-objects-without-prototypes.html)

Comment by Kurt Harriger [ 22/Mar/18 5:55 PM ]

The above also suggests that maybe one could extend IEncodeClojure on nil?
`a` is not `nil` but its type is... so maybe extending protocol on nil should this work?

But it doesn't... maybe this is a bug in `satisfies?`?

```
cljs.user=> (def a (.create js/Object nil))
#'cljs.user/a
cljs.user=> (aset a "test" 1)
1
cljs.user=> (extend-protocol IEncodeClojure
nil
(js>clj [x opts]
(let [{:keys [keywordize-keys]} opts
keyfn (if keywordize-keys keyword str)]
(into {} (for [k (js-keys x)]
[(keyfn k) (js->clj (unchecked-get x k)) opts])))))
nil
cljs.user=> (js->clj a)
#object[Object]
cljs.user=> (js-keys IEncodeClojure)
#js ["null"]
cljs.user=> (satisfies? IEncodeClojure a)
false
cljs.user=> (type a)
nil

```

Comment by Hendrik Poernama [ 25/Apr/18 4:04 AM ]

What about `(identical? (goog/typeOf x) "object")` instead of `(identical? (type x) js/Object)`?

Closure's typeOf correctly returns 'null' and 'array' and has some browser specific fixes.
Current test looks like a lot less code, so may need to performance test.

Example:
(identical? "object" (goog/typeOf (.create js/Object nil #js {:a #js {:value 1}}))) => true





[CLJS-2742] lein-doo fails with Clojurescript 1.10.238 (AOT version) Created: 22/Apr/18  Updated: 23/Apr/18  Resolved: 23/Apr/18

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

Type: Defect Priority: Major
Reporter: Joel Sánchez López Assignee: Unassigned
Resolution: Not Reproducible Votes: 0
Labels: None


 Description   

Running this command: `lein doo chrome-headless test once`
Results in:

```
Exception in thread "main" java.lang.NoSuchMethodError: cljs.js_deps.IJavaScript._url(Ljava/lang/Object;)Ljava/lang/Object;, compiling/tmp/form-init7914580949796230591.clj:1:73)
at clojure.lang.Compiler.load(Compiler.java:7526)
at clojure.lang.Compiler.loadFile(Compiler.java:7452)
at clojure.main$load_script.invokeStatic(main.clj:278)
at clojure.main$init_opt.invokeStatic(main.clj:280)
at clojure.main$init_opt.invoke(main.clj:280)
at clojure.main$initialize.invokeStatic(main.clj:311)
at clojure.main$null_opt.invokeStatic(main.clj:345)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Caused by: java.lang.NoSuchMethodError: cljs.js_deps.IJavaScript._url(Ljava/lang/Object;)Ljava/lang/Object;
at cljs.closure$rel_output_path.invokeStatic(closure.clj:1706)
at cljs.closure$rel_output_path.invoke(closure.clj:1698)
at cljs.closure$write_javascript.invokeStatic(closure.clj:1856)
at cljs.closure$write_javascript.invoke(closure.clj:1850)
at cljs.closure$source_on_disk.invokeStatic(closure.clj:1899)
at cljs.closure$source_on_disk.invoke(closure.clj:1894)
at cljs.closure$build$fn__5906.invoke(closure.clj:2825)
at clojure.core$map$fn__5587.invoke(core.clj:2747)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:528)
at clojure.core$seq__5124.invokeStatic(core.clj:137)
at clojure.core$dorun.invokeStatic(core.clj:3125)
at clojure.core$doall.invokeStatic(core.clj:3140)
at clojure.core$doall.invoke(core.clj:3140)
at cljs.closure$build.invokeStatic(closure.clj:2825)
at cljs.closure$build.invoke(closure.clj:2718)
at cljs.build.api$build.invokeStatic(api.clj:208)
at cljs.build.api$build.invoke(api.clj:189)
at cljs.build.api$build.invokeStatic(api.clj:195)
at cljs.build.api$build.invoke(api.clj:189)
at user$eval27281.invokeStatic(form-init7914580949796230591.clj:1)
at user$eval27281.invoke(form-init7914580949796230591.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.eval(Compiler.java:7052)
at clojure.lang.Compiler.load(Compiler.java:7514)
... 12 more
Subprocess failed
```

See https://github.com/JoelSanchez/cljs-aot-doo-repro



 Comments   
Comment by Joel Sánchez López [ 22/Apr/18 3:03 PM ]

Second repro, with cljsbuild (no doo involved):
https://github.com/JoelSanchez/cljs-aot-cljsbuild-repro

Comment by Joel Sánchez López [ 22/Apr/18 4:44 PM ]

Turns out I was depending on 'tubular', which in turn was depending on 'clojure.core.typed'. A new 'tubular' release fixed the issue.
Please someone close this...I can't.





[CLJS-2740] (cljs.reader/register-tag-parser! ...) fails with version 1.10.x but ok with 1.9.671 Created: 20/Apr/18  Updated: 20/Apr/18  Resolved: 20/Apr/18

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

Type: Defect Priority: Critical
Reporter: Denis Johnson Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: bug

Attachments: File core.cljs    

 Description   

An existing project extends protocol IPrintWithWriter and registers tag via cljs.reader/register-tag-parser!
Round trips write to string via pr-str and read-string.

With deps < 1.9.x code as per core.cljs attached works as expected

[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.671"]

With deps 1.10.x code as per core.cljs attached compiles but throws runtime error in our unit test "No reader function for tag utc."

[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.10.238"]

This is preventing us from upgrading our projects to the 1.10.x series of clojurescript which in turn is blocking us from other dep updates like reagent 0.8.0 so we consider this critical.



 Comments   
Comment by Thomas Heller [ 20/Apr/18 1:46 AM ]

FYI register-tag-parser! expects a symbol, eg. (reader/register-tag-parser! 'utc ...).

Comment by Denis Johnson [ 20/Apr/18 3:00 AM ]

Nice catch Thomas ! it has been working like this for some years and certainly not obvious to me from cljs.reader/register-tag-parser! but my tests pass again with 1.10.238 so I'm happy. Thanks.

Comment by Mike Fikes [ 20/Apr/18 6:34 AM ]

Perhaps this is a consequence of the changes made for CLJS-1800. If so, we'd just need to determine if this constitutes a regression or if the older code in the ticket was simply working accidentally.

Comment by David Nolen [ 20/Apr/18 9:02 AM ]

This intentionally does not work anymore.





[CLJS-1561] WARN if recur passes non-inferred type Created: 06/Feb/16  Updated: 16/Apr/18

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

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

Attachments: Text File CLJS-1561-2.patch     Text File CLJS-1561-3.patch     Text File CLJS-1561-4.patch     Text File CLJS-1561.patch    
Patch: Code and Test

 Description   

Take this code as an example:

(defn f [^boolean b]
  (loop [x b]
    (if x
      (recur 0)
      :done)))

The type of x is inferred to be Boolean, but there is a recur form that can be statically deduced to be passing a non-Boolean.

This ticket asks that a WARN be issued for this case, and perhaps others (where maybe x itself is directly type hinted).



 Comments   
Comment by Mike Fikes [ 06/Feb/16 2:59 PM ]

Attached a patch which warns on for the case of boolean and number, since those two types have special handling.

Some example usage:

cljs.user=> (defn f [^boolean b]
       #_=>   (loop [x b]
       #_=>     (if x
       #_=>       (recur 0)
       #_=>       :done)))
WARNING: recur target parameter x has inferred type boolean, but being passed type number at line 4 
#'cljs.user/f
cljs.user=> (loop [x 1 y true z :hi]
       #_=>   (when false (recur 'a "hi" nil)))
WARNING: recur target parameter x has inferred type number, but being passed type cljs.core/Symbol at line 2 
WARNING: recur target parameter y has inferred type boolean, but being passed type string at line 2 
nil
cljs.user=> (loop [x 1 y true]
       #_=>  (when false (recur nil nil)))
WARNING: recur target parameter x has inferred type number, but being passed type clj-nil at line 2 
WARNING: recur target parameter y has inferred type boolean, but being passed type clj-nil at line 2 
nil
cljs.user=> (loop [x 1]
       #_=>   (let [y (inc x)]
       #_=>     (when false (recur (inc y)))))
nil
cljs.user=> (loop [b true]
       #_=>   (when false (recur (inc 1))))
WARNING: recur target parameter b has inferred type boolean, but being passed type number at line 2 
cljs.user=> (loop [x 1] 
       #_=>   (inc x) 
       #_=>     (when false (recur :hi)))
WARNING: recur target parameter x has inferred type number, but being passed type cljs.core/Keyword at line 3 
nil
cljs.user=> (loop [x :hello] 
       #_=>   (inc x) 
       #_=>     (when false (recur :hi)))
WARNING: cljs.core$macros/+, all arguments must be numbers, got [cljs.core/Keyword number] instead. at line 2 
nil
Comment by Mike Fikes [ 13/Jun/17 9:31 PM ]

Assigning to take another look at this. The all of the examples provided in this ticket are still working apart from the first, which no longer appears to cause the diagnostic to be emitted.

Comment by Mike Fikes [ 21/Feb/18 1:46 PM ]

Re-baselined on master, confirmed that the first example is now working again, added a new needed suppression for js type (to go along with any), and added analyzer unit tests covering the cases in the comments above so they need not be validated manually.

Comment by Mike Fikes [ 14/Mar/18 8:11 PM ]

CLJS-1561-3.patch rebaselines

Comment by Mike Fikes [ 16/Apr/18 7:53 AM ]

Assigning back to me to look at warnings being triggered:

WARNING: recur target parameter count__1928 has inferred type number, but being passed type #{any number} at line 302 /Users/mfikes/.cljs/.aot_cache/1.10.271/9986866/cljs/pprint.cljs
WARNING: recur target parameter count__1962 has inferred type number, but being passed type #{any number} at line 470 /Users/mfikes/.cljs/.aot_cache/1.10.271/9986866/cljs/pprint.cljs
WARNING: recur target parameter count__2756 has inferred type number, but being passed type #{any number} at line 3322 /Users/mfikes/.cljs/.aot_cache/1.10.271/9986866/cljs/pprint.cljs
WARNING: recur target parameter count__3027 has inferred type number, but being passed type #{any number} at line 237 /Users/mfikes/.cljs/.aot_cache/1.10.271/B027069/cljs/spec/alpha.cljs
WARNING: recur target parameter count__3021 has inferred type number, but being passed type #{any number} at line 224 /Users/mfikes/.cljs/.aot_cache/1.10.271/B027069/cljs/spec/alpha.cljs
WARNING: recur target parameter count__3039 has inferred type number, but being passed type #{any number} at line 237 /Users/mfikes/.cljs/.aot_cache/1.10.271/B027069/cljs/spec/alpha.cljs
WARNING: recur target parameter count__3049 has inferred type number, but being passed type #{any number} at line 242 /Users/mfikes/.cljs/.aot_cache/1.10.271/B027069/cljs/spec/alpha.cljs
WARNING: recur target parameter count__3584 has inferred type number, but being passed type #{any number} at line 19 /Users/mfikes/.cljs/.aot_cache/1.10.271/C3CEC05/cljs/repl.cljs
WARNING: recur target parameter count__3588 has inferred type number, but being passed type #{any number} at line 45 /Users/mfikes/.cljs/.aot_cache/1.10.271/C3CEC05/cljs/repl.cljs
WARNING: recur target parameter count__3602 has inferred type number, but being passed type #{any number} at line 54 /Users/mfikes/.cljs/.aot_cache/1.10.271/C3CEC05/cljs/repl.cljs




[CLJS-2619] clojure.reflect needs exclude for macroexpand Created: 05/Mar/18  Updated: 13/Apr/18  Resolved: 13/Apr/18

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-2619.patch    
Patch: Code

 Description   
cljs.user=> (require 'clojure.reflect)
WARNING: macroexpand already refers to: cljs.core/macroexpand being replaced by: clojure.reflect/macroexpand at line 33 /Users/mfikes/.cljs/.aot_cache/1.10.132/3837055/clojure/reflect.cljs


 Comments   
Comment by David Nolen [ 13/Apr/18 4:05 PM ]

fixed https://github.com/clojure/clojurescript/commit/132d3aa232921a3cea66f830d61c89be78c581cb





[CLJS-2713] test-reader fails on Windows Created: 27/Mar/18  Updated: 13/Apr/18  Resolved: 13/Apr/18

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: windows

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

 Description   

SpiderMonkey:

Testing cljs.reader-test

FAIL in (test-reader) (core-advanced-test.js:1271:77)
Character Literals
expected: (= ["\t" "\r" "\n" " " "\b" "\f" "?"] (reader/read-string "[\\tab \\return \\newline \\space \\backspace \\formfeed \\u1234]"))
  actual: (not (= ["\t" "\r" "\n" " " "\b" "\f" "?"] ["\t" "\r" "\n" " " "\b" "\f" "ሴ"]))

ChakraCore:

Testing cljs.reader-test

FAIL in (test-reader) (at Anonymous function (C:1277:245)
Character Literals
expected: (= ["\t" "\r" "\n" " " "\b" "\f" "?"] (reader/read-string "[\\tab \\return \\newline \\space \\backspace \\formfeed \\u1234]"))
  actual: (not (= ["\t" "\r" "\n" " " "\b" "\f" "?"] ["\t" "\r" "\n" " " "\b" "\f" "ሴ"]))


 Comments   
Comment by Mike Fikes [ 29/Mar/18 6:49 AM ]

I tried but failed to reproduce the logic of this unit test in the Node REPL on Windows, even when the source of the test comes from a file.

I've also tried changing the optimization settings to :whitespace and it still repros in CI.

I've taken the core-advanced-test.js produced on macOS and copied them to Windows and run them through ChakraCore ch.exe and the tests pass that way.

The above seems to imply that it is either the CI environment or or bad code being emitted by the compiler under Windows. Further investigation is needed.

Comment by Mike Fikes [ 02/Apr/18 9:03 PM ]

I've confirmed that if you build core-advanced-test.js on Windows and then copy it to macOS, then the tests fail in the same way on macOS under JavaScriptCore (jsc). This implies that incorrect code is being generated either by the ClojureScript compiler or Closure on Windows.

If you instead compile with :whitespace you can see a difference in the compiled code, with a difference here:

Compiled on Windows:

"Character Literals");try{try{var values__15370__auto___22374=new cljs.core.List(null,new cljs.core.PersistentVector(null,7,5,cljs.core.PersistentVector.EMPTY_NODE,["\t","\r",
"\n"," ","\b","\f","?"],null)

Compiled on macOS:

"Character Literals");try{try{var values__16783__auto___21003=new cljs.core.List(null,new cljs.core.PersistentVector(null,7,5,cljs.core.PersistentVector.EMPTY_NODE,["\t","\r",
"\n"," ","\b","\f","ሴ"],null)

Tracing is back to the code generated into cljs\reader_test.js you can see that the problem is probably rooted in a failure to deal with the string "\u1234" by Closure on Windows as this string form is generated identically on both Windows and macOS.

Windows:

"Character Literals");

try{try{var values__15370__auto___22374 = (new cljs.core.List(null,new cljs.core.PersistentVector(null, 7, 5, cljs.core.PersistentVector.EMPTY_NODE, ["\t","\r","\n"," ","\b","\f","\u1234"], null)

macOS:

"Character Literals");

try{try{var values__16783__auto___21003 = (new cljs.core.List(null,new cljs.core.PersistentVector(null, 7, 5, cljs.core.PersistentVector.EMPTY_NODE, ["\t","\r","\n"," ","\b","\f","\u1234"], null)

I am unable to reproduce the problem directly with Closure via

java -jar compiler.jar --js test.js --js_output_file test-compiled.js --charset UTF-8

with

test.js
alert("\u1234");
Comment by Mike Fikes [ 07/Apr/18 10:34 AM ]

The root problem is likely that print output being generated by bin\cljsc.bat ends up being improperly encoded, when we need UTF8. While the default encoding for PowerShell's Set-Content cmdlet is ASCII, revising it to specify -Encoding UTF8 does not fix the issue. So, the approach in the patch is to avoid piping the output of bin\cljsc.bat altogether and to instead just rely on :output-to to write the file with the proper encoding (which directly uses spit from within the compiler).

Comment by David Nolen [ 13/Apr/18 4:04 PM ]

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





[CLJS-2715] Have goog-define return the var at the REPL Created: 28/Mar/18  Updated: 13/Apr/18  Resolved: 13/Apr/18

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-2715.patch    
Patch: Code

 Description   

Currently, goog-define returns nil. It actually defines a specially-annotated, but otherwise regular var. For didactic and consistency purposes, it would be nice for goog-define to return the var only when at the REPL.

The behavior would look like:

$ clj -m cljs.main -co '{:closure-defines {foo.core/bar 11}}' -r
cljs.user=> (ns foo.core)

foo.core=> (goog-define bar 10)
#'foo.core/bar
foo.core=> bar
11


 Comments   
Comment by Mike Fikes [ 28/Mar/18 1:12 PM ]

The attached patch does this without adding any code bloat in the non-REPL path, while also trying to not over-complicate the existing code (by conditionally employing a wrapper macro instead of do).

Comment by David Nolen [ 13/Apr/18 3:16 PM ]

fixed https://github.com/clojure/clojurescript/commit/9dc684695cee889001d36fbe0753c8aae8dc209b





[CLJS-2722] result of eval-str callback no longer returned Created: 03/Apr/18  Updated: 13/Apr/18  Resolved: 13/Apr/18

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

Type: Defect