├── .github └── workflows │ └── main.yml ├── .gitignore ├── LICENSE ├── README.adoc ├── assets └── images │ └── content │ ├── guides │ └── quick-start │ │ └── browser.png │ └── news │ └── 2018-03-26-clojurescript-command-line │ ├── blue-circle.png │ ├── blue-red-circle.png │ └── browser.png ├── content ├── 404.adoc ├── about │ ├── closure.adoc │ ├── differences.adoc │ ├── functional-programming.adoc │ └── rationale.adoc ├── community │ ├── books.adoc │ ├── building.adoc │ ├── closure.adoc │ ├── companies.adoc │ ├── contributing.adoc │ ├── contributing_site.adoc │ ├── custom-repls.adoc │ ├── dev.adoc │ ├── editing.adoc │ ├── libraries.adoc │ ├── license.adoc │ ├── patches.adoc │ ├── reporting-bootstrap-issues.adoc │ ├── reporting-issues.adoc │ ├── resources.adoc │ └── running-tests.adoc ├── guides │ ├── code-splitting.adoc │ ├── externs.adoc │ ├── faq-js.adoc │ ├── faq.adoc │ ├── guides.adoc │ ├── javascript-modules.adoc │ ├── native-executables.adoc │ ├── ns-forms.adoc │ ├── project-templates.adoc │ ├── promise-interop.adoc │ ├── quick-start.adoc │ ├── reader.adoc │ ├── self-hosting.adoc │ └── webpack.adoc ├── news │ ├── 2017-06-26-welcome.adoc │ ├── 2017-06-27-faster-compilation-runtime-and-spec-caching-fixes.adoc │ ├── 2017-07-07-sneak-preview.adoc │ ├── 2017-07-10-code-splitting.adoc │ ├── 2017-07-12-clojurescript-is-not-an-island-integrating-node-modules.adoc │ ├── 2017-07-14-checked-array-access.adoc │ ├── 2017-07-20-js-preprocessing-improvements.adoc │ ├── 2017-07-28-release-candidate.adoc │ ├── 2017-07-30-global-exports.adoc │ ├── 2017-08-16-release.adoc │ ├── 2017-08-16-release.adoc copy │ ├── 2017-10-03-release.adoc │ ├── 2018-03-26-clojurescript-command-line.adoc │ ├── 2018-03-26-release.adoc │ ├── 2018-03-28-shared-aot-cache.adoc │ ├── 2018-06-15-release.adoc │ ├── 2018-11-02-release.adoc │ ├── 2019-01-31-release.adoc │ ├── 2019-11-18-release.adoc │ ├── 2020-04-24-bundle-target.adoc │ ├── 2020-04-24-release.adoc │ ├── 2021-04-06-release.adoc │ ├── 2021-05-24-release.adoc │ ├── 2021-11-04-release.adoc │ ├── 2021-12-20-release.adoc │ ├── 2022-05-13-release.adoc │ ├── 2024-01-24-release.adoc │ ├── 2025-05-16-release.adoc │ └── news.adoc ├── privacy.adoc ├── reference │ ├── advanced-compilation.adoc │ ├── bootstrapping.adoc │ ├── compiler-options.adoc │ ├── dependencies.adoc │ ├── documentation.adoc │ ├── google-closure-library.adoc │ ├── javascript-api.adoc │ ├── javascript-library-preprocessing.adoc │ ├── javascript-module-support.adoc │ ├── packaging-foreign-deps.adoc │ ├── repl-and-main.adoc │ ├── repl-options.adoc │ ├── repl.adoc │ └── source-maps.adoc ├── search.adoc └── tools │ ├── atom.adoc │ ├── cursive.adoc │ ├── emacs-inf.adoc │ ├── leiningen.adoc │ ├── light-table.adoc │ ├── shadow-cljs.adoc │ ├── sublime.adoc │ ├── testing.adoc │ ├── tools.adoc │ ├── vim.adoc │ └── vscode.adoc └── scripts └── trigger /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Trigger publish 14 | run: curl -X POST -H "Authorization:token ${{ secrets.GH_TOKEN }}" -H "Accept:application/vnd.github.v3+json" --data '{"event_type":"publish"}' https://api.github.com/repos/clojure/clojurescript-org-style/dispatches 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /target 3 | /classes 4 | /checkouts 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | *.iml 10 | *.zip 11 | /.lein-* 12 | /.nrepl-port 13 | /.idea 14 | .hgignore 15 | .hg/ 16 | jbake.properties 17 | /output 18 | /assets/css 19 | /assets/fonts 20 | /assets/js 21 | /assets/favicon.ico 22 | /assets/images/*.png 23 | /assets/images/*.svg 24 | /assets/images/theme 25 | /templates 26 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = README 2 | Alex Miller 3 | 2016-07-29 4 | :jbake-type: page 5 | :toc: macro 6 | 7 | This web site is an open-source repository of content about the ClojureScript programming language and its greater ecosystem, hosted at http://clojurescript.org. 8 | 9 | == Contributing 10 | 11 | If you wish to point out an issue in the site or propose a new page, you can do so by filing a GitHub issue at https://github.com/clojure/clojurescript-site/issues. 12 | 13 | If you wish to make a contribution (typo, modification, or new content), you must become a contributor and follow the https://github.com/clojure/clojurescript-site/blob/master/content/community/contributing_site.adoc[contribution process]. 14 | 15 | == Building the Site 16 | 17 | The site is built using http://jbake.org/[JBake]. 18 | 19 | To http://jbake.org/docs/2.4.0/#installation[install] JBake 2.5.0-SNAPSHOT: 20 | 21 | . `curl -O http://cdn.cognitect.com/clojurescript.org/jbake-2.5.0-SNAPSHOT-bin.zip` (or download this file with your browser) 22 | . `unzip -o jbake-2.5.0-SNAPSHOT-bin.zip` 23 | . Add jbake-2.5.0-SNAPSHOT/bin to your system PATH 24 | 25 | To build the site: 26 | 27 | Retrieve the content: 28 | 29 | . `git clone https://github.com/clojure/clojurescript-site.git` (or your own fork) 30 | . `cd clojurescript-site` 31 | 32 | Retrieve and install the current theme assets (these don't change very often so you don't need to do this every time): 33 | 34 | . `curl -O https://clojurescript.org/cljstheme.zip` (or download this file with your browser to the clojurescript-site directory) 35 | . `unzip -o cljstheme.zip` 36 | 37 | Generate the pages: 38 | 39 | > Note that `jbake` 2.5.0 requires Java 8. (It will not run properly under Java 9.) 40 | 41 | . `jbake` - this will create the static site in the output directory 42 | . Run `jbake -s` to serve these pages at http://localhost:8820/index 43 | 44 | ## Terms of Use 45 | 46 | Copyright © 2015 Rich Hickey and contributors 47 | 48 | All documentation contained in this repository is licensed by Rich Hickey under the http://www.eclipse.org/legal/epl-v10.html[Eclipse Public License v1.0] unless otherwise noted. To submit a pull request or other contribution, you must sign the http://clojurescript.org/community/contributing[Clojure Contributor Agreement]. 49 | -------------------------------------------------------------------------------- /assets/images/content/guides/quick-start/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clojure/clojurescript-site/2f0a8f471324420eab024b6415f45116e9e60cdb/assets/images/content/guides/quick-start/browser.png -------------------------------------------------------------------------------- /assets/images/content/news/2018-03-26-clojurescript-command-line/blue-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clojure/clojurescript-site/2f0a8f471324420eab024b6415f45116e9e60cdb/assets/images/content/news/2018-03-26-clojurescript-command-line/blue-circle.png -------------------------------------------------------------------------------- /assets/images/content/news/2018-03-26-clojurescript-command-line/blue-red-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clojure/clojurescript-site/2f0a8f471324420eab024b6415f45116e9e60cdb/assets/images/content/news/2018-03-26-clojurescript-command-line/blue-red-circle.png -------------------------------------------------------------------------------- /assets/images/content/news/2018-03-26-clojurescript-command-line/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clojure/clojurescript-site/2f0a8f471324420eab024b6415f45116e9e60cdb/assets/images/content/news/2018-03-26-clojurescript-command-line/browser.png -------------------------------------------------------------------------------- /content/404.adoc: -------------------------------------------------------------------------------- 1 | = Page Not Found 2 | Rich Hickey 3 | 2015-01-01 4 | :type: notfound 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | We're sorry, that page could not be found on this site. 11 | -------------------------------------------------------------------------------- /content/about/closure.adoc: -------------------------------------------------------------------------------- 1 | = Google Closure 2 | Rich Hickey 3 | 2016-07-29 4 | :type: about 5 | :toc: macro 6 | :icons: font 7 | :navlinktext: Google Closure 8 | :prevpagehref: differences 9 | :prevpagetitle: Differences from Clojure 10 | 11 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 12 | 13 | toc::[] 14 | 15 | == Motivations for using Google's Closure Tools 16 | 17 | Clojure is nothing if not practical and ClojureScript is no different. As more and more applications target web and mobile environments, the role and reach of JavaScript likewise expands beyond the confines of the browser into even more constrained environments such as mobile with ubiquitous networked paths between nodes. The Google Closure tools provides a robust set of http://code.google.com/closure/library/[libraries], a strong http://code.google.com/closure/library/docs/introduction.html#deps[dependency management system], and a sophisticated http://code.google.com/closure/compiler/[compiler] each working toward an ultimate goal of reducing JavaScript code size. For ClojureScript, Google Closure provides a solution to the "library problem" for JavaScript in three distinct ways: 18 | 19 | * Libraries 20 | * Dependency management 21 | * Aggressive code minification 22 | 23 | Each of these features represents thousands of hours of research, design, development, and testing. Therefore ClojureScript leverages them in its implementation, allowing the Clojure/core team and contributors to focus on enabling the power of Clojure wherever JavaScript is found. 24 | 25 | === Libraries 26 | 27 | ClojureScript is written in Clojure and ClojureScript interoperating with the Google Closure JavaScript libraries. However, ClojureScript can interoperate with *any* JavaScript library or framework. The use of the https://developers.google.com/closure/library/docs/overview[Google Closure] libraries in the ClojureScript core is an implementation strategy allowing us to reduce dependencies and ensure compatibility with advanced mode compilation (see below). 28 | 29 | === Dependency Management 30 | 31 | Google Closure's dependency management system offers three primitives `addDependency`, `provide`, and `require` that enable compile-time dependency inclusions. ClojureScript encapsulates these, providing access through the `ns` form. This capability is leveraged to allow fine-grained imports and exports of ClojureScript namespaces and functions and also external JavaScript libraries for interoperability purposes. 32 | 33 | === Compiler 34 | 35 | Google's Closure Tools provide a http://en.wikipedia.org/wiki/Minification_(programming)[minification compiler] available to the ClojureScript compilation process via command-line flags. In summary, the minification compiler receives generated JavaScript produced by the ClojureScript compiler and renames variables to shorter names, removes whitespace, removes comments, etc. in an effort to reduce the source size while maintaining the program semantics. 36 | 37 | ==== Dead code analysis 38 | 39 | http://code.google.com/closure/compiler/[Google's Closure compiler] provides an http://code.google.com/closure/compiler/docs/api-tutorial3.html[advanced setting] allowing a much more aggressive minification strategy than that outlined above. In fact, the Google Closure compiler uses highly sophisticated techniques for identifying and eliminating dead code (i.e. code that is never called nor reachable). The downside of this fact is that the style of the JavaScript code must http://code.google.com/closure/compiler/docs/limitations.html[conform to a strict standard] in order to achieve maximum minification potential. Therefore, it is the goal of the ClojureScript team to ensure that the generated JavaScript code is maximally minifiable through an observance to said idioms and through the use of the Closure libraries and dependency system. 40 | 41 | === Learn More 42 | 43 | image:http://covers.oreilly.com/images/0636920001416/cat.gif[Closure: The Definitive Guide] 44 | 45 | The primary reference for the Google Closure tools is O'Reilly's *http://oreilly.com/catalog/0636920001416[Closure: The Definitive Guide]* written by Michael Bolin. This book is highly recommended for anyone hoping to leverage the full power of ClojureScript interoperability, for ClojureScript contributors, and for those simply curious about advanced JavaScript techniques and tools. 46 | -------------------------------------------------------------------------------- /content/about/rationale.adoc: -------------------------------------------------------------------------------- 1 | = Rationale 2 | Rich Hickey 3 | 2016-07-29 4 | :type: about 5 | :toc: macro 6 | :icons: font 7 | :navlinktext: Rationale 8 | :nextpagehref: differences 9 | :nextpagetitle: Differences from Clojure 10 | 11 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 12 | 13 | toc::[] 14 | 15 | == JavaScript's Reach 16 | 17 | There are many environments (e.g. browsers) in which JavaScript is the only programmable technology. There are others (e.g. mobile) where JavaScript is the most portable development approach. And JavaScript is widely used as an extension or scripting language, e.g. as an extension or indexing language in a database. 18 | 19 | == JavaScript is not Robust 20 | 21 | However, even JavaScript's proponents will acknowledge its shortcomings. There are many dark corners in the language semantics. It is not particularly concise, and it's not well suited for metaprogramming or extension. Most troubling is that writing robust JavaScript programs, while possible, requires a combination of extensive discipline and convention, and conventions differ between development shops, communities and libraries. 22 | 23 | == Client-service Applications are on the Rise 24 | 25 | Initial use of JavaScript was oriented towards adding interaction to document/page oriented sites closely aligned to the linked hypertext design of the web. Increasingly JavaScript is being used to construct client-service applications (e.g. Google's apps), where the JavaScript represents an ongoing piece of logic, data, and UI connected to one or more network accessible services. Such applications place much greater demands on their JavaScript hosted portions. 26 | 27 | == JavaScript Engines Gain Power 28 | 29 | As JavaScript has been called upon to do more and more, JavaScript engines have moved from simple interpreters to quite sophisticated and high performance execution platforms involving native code generation and classic and novel dynamic language optimizations. The engines, in the large, are specifically oriented towards JavaScript semantics and execution, i.e. they are not as general as the JVM and CLR. 30 | 31 | == Google Leads the Way 32 | 33 | As the leading purveyor of client-service applications, with tremendous resources and a vested interest in web-hosted applications, Google has cutting-edge technology in this area. From the V8 JS engine to the whole-program optimizing symbiotic pair of Closure library and the Closure compiler, Google has open sourced the most advanced technology available in this area. It is worthwhile to understand and leverage what they have provided. 34 | 35 | == The Library Problem 36 | 37 | As applications are asked to do more, developers will seek to use more, and larger, libraries. But many of the target platforms are memory constrained, or network connected, and there is much pressure to reduce code size. Minification makes each library smaller, but minification alone still dictates a code size equal to the sum of the minified library sizes. However, applications rarely use all of the code in the libraries they consume. Whole program optimization can be used to construct an application whose code size footprint consists only of the code actually used, regardless of the number or size of the libraries utilized. This is the strategy pursued by the Google Closure library and compiler pair. 38 | 39 | = Opportunity 40 | 41 | A development platform with extensive reach, portability, multi-vendor support, an optimization arms race, sophisticated tools, implemented on all new devices, and a call for richer and more sophisticated applications - what more could developers want? A different language, that's what. While efforts are underway to improve JavaScript, you can't significantly improve something with extensive reach in a timely manner - your improved version won't have the same reach for a long time, if ever. Thus JavaScript _as it currently exists_ is a given, and becomes the target, rather than the source language. 42 | 43 | == ClojureScript 44 | 45 | ClojureScript seeks to address the weak link in the client/embedded application development story by replacing JavaScript with Clojure, a robust, concise and powerful programming language. In its implementation, ClojureScript adopts the strategy of the Google Closure library and compiler, and is able to effectively leverage both tools, gaining a large, production-quality library and whole-program optimization. ClojureScript brings the rich data structure set, functional programming, macros, reader, destructuring, polymorphism constructs, state discipline and many other features of Clojure to every place JavaScript reaches. -------------------------------------------------------------------------------- /content/community/books.adoc: -------------------------------------------------------------------------------- 1 | = Books {amp} Videos 2 | David Nolen 3 | 2017-07-06 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | Please support these fine books and videos about ClojureScript. 9 | 10 | === Books 11 | 12 | [width="50", cols="<.^30a,.^70", role="table"] 13 | |=== 14 | 15 | | image::https://www.learn-clojurescript.com/img/learn-clojurescript-cover.jpg[Learn ClojureScript, link="https://gum.co/learn-cljs"] 16 | | https://gum.co/learn-cljs[Learn ClojureScript] + 17 | by Andrew Meredith + 18 | March 2021 19 | 20 | | image::https://www.packtpub.com/sites/default/files/7635cov_.jpg[Learning ClojureScript, link="https://www.packtpub.com/web-development/learning-clojurescript"] 21 | | https://www.packtpub.com/web-development/learning-clojurescript[Learning ClojureScript] + 22 | by W. David Jarvis, Rafik Naccache, Allen Rohner + 23 | June 2016 24 | 25 | | image::https://s3.amazonaws.com/titlepages.leanpub.com/clojurescript-unraveled/hero?1437124942[ClojureScript Unraveled, link="https://leanpub.com/clojurescript-unraveled"] 26 | | https://leanpub.com/clojurescript-unraveled[ClojureScript Unraveled] + 27 | by Andrey Antukh and Alejandro Gómez + 28 | June 25, 2016 29 | 30 | | image::https://covers.oreillystatic.com/images/0636920043584/cat.gif[Etudes for ClojureScript] 31 | | https://shop.oreilly.com/product/0636920043584.do[Etudes for ClojureScript] + 32 | by J. Eisenberg + 33 | November 2015 34 | 35 | | image::https://ecx.images-amazon.com/images/I/51KgF%2B-38WL._SL160.jpg[ClojureScript: Up and Running,link="https://amzn.com/1449327435"] 36 | | https://amzn.com/1449327435[ClojureScript: Up and Running] + 37 | by Stuart Sierra, Luke VanderHart + 38 | Nov 10, 2012 39 | 40 | |=== 41 | 42 | === Videos 43 | 44 | * https://www.learnreframe.com/[Learn re-frame] 45 | * https://www.learnreagent.com/[Learn Reagent] 46 | * https://lambdaisland.com[Lambda Island] 47 | * https://purelyfunctional.tv[PurelyFunctional.tv] 48 | * https://shop.oreilly.com/product/0636920040316.do[Learning ClojureScript] 49 | -------------------------------------------------------------------------------- /content/community/building.adoc: -------------------------------------------------------------------------------- 1 | = Building the compiler 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | Make sure you have Maven and at least Java 8 installed. If you don't already 11 | have them, use a system specific package manager like `apt-get` or `brew`. 12 | 13 | Checkout https://github.com/clojure/clojurescript[the git repository], switch 14 | into the checkout and run: 15 | 16 | [source,bash] 17 | ---- 18 | script/build 19 | ---- 20 | 21 | At the end of the build output you will see a line similar to the one 22 | below, but with different version numbers. 23 | 24 | [source,bash] 25 | ---- 26 | [INFO] Installing <...>/clojurescript/target/clojurescript-1.7.164-aot.jar to /Users/username/.m2/repository/org/clojure/clojurescript/1.7.164/clojurescript-1.7.164-aot.jar 27 | ---- 28 | 29 | This shows that ClojureScript 1.7.164 has been built, and is installed 30 | in your local Maven repo. To use it, specify your ClojureScript 31 | dependency as `[org.clojure/clojurescript "1.7.164"]` (but with the 32 | version number that you built). 33 | -------------------------------------------------------------------------------- /content/community/closure.adoc: -------------------------------------------------------------------------------- 1 | = Dev 2 | David Nolen 3 | 2018-03-25 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | [[closure-compiler-development]] 11 | == Closure Compiler Development 12 | 13 | ClojureScript has deep integration with https://github.com/google/closure-compiler[Google Closure Compiler]. 14 | Many ClojureScript features like Node / ES6 modules processing are actually provided 15 | through Google Closure Compiler support. In these areas, contribution to 16 | ClojureScript is done by contributing directly to the Google Closure compiler 17 | project itself. 18 | 19 | === Contributing to Closure Compiler 20 | 21 | The Closure compiler team uses GitHub to manage the project and are particularly 22 | responsive to issues if they are accompanied by pull requests that provide 23 | resolutions. In order to contribute to the Closure Compiler project, you must 24 | submit a Google Contributor Agreement. 25 | 26 | === Closure Compiler Development 27 | 28 | While sparsely documented, the Closure Compiler Java code base is surprisingly 29 | approachable. Using a free Java IDE like 30 | https://www.jetbrains.com/idea/download/[IntelliJ Community Edition] can greatly 31 | simplify exploring and understanding the Closure Compiler source. When locating 32 | the source of Closure Compiler bugs, Java IDEs also have the added benefit of 33 | robust step debugging tools. 34 | 35 | Once you believe you have a fix, create a branch with your fixes and then create 36 | a test case. 37 | 38 | ==== Adding a Test Case to Closure Compiler 39 | 40 | Find an appropriate test case file for your unit test. To test your specific 41 | test you must first build Closure Compiler: 42 | 43 | ``` 44 | mvn clean && mvn -DskipTests -pl externs/pom.xml,pom-main.xml,pom-main-shaded.xml 45 | ``` 46 | 47 | At this point unless you need to recompile your compiler changes you can simply 48 | compile and run your test case which takes less time. In the following replace 49 | `TestClass#testMethod` with the class and method that you are testing. 50 | 51 | ``` 52 | mvn -pl pom-main.xml compiler:testCompile surefire:test -Dtest=TestClass#testMethod 53 | ``` 54 | 55 | Once your tests are passing create a branch if you haven't already with your 56 | fixes and submit a pull request. Your pull request should probably be linked 57 | to a corresponding GitHub issue. 58 | 59 | The final step is to verify that your fix actually addresses the issue in 60 | ClojureScript. 61 | 62 | ==== Testing Closure Compiler against ClojureScript 63 | 64 | Build Closure Compiler: 65 | 66 | ``` 67 | mvn clean && mvn -DskipTests -pl externs/pom.xml,pom-main.xml,pom-main-unshaded.xml 68 | ``` 69 | 70 | This will install the unshaded JAR in your local maven, take note of the 71 | version. In the ClojureScript repo change the dependency information for 72 | the Closure Compiler artifact using whichever tool your prefer (i.e. edit 73 | project.clj or deps.edn). 74 | 75 | Test that the ClojureScript issue is resolved via a ClojureScript specific test. 76 | -------------------------------------------------------------------------------- /content/community/contributing.adoc: -------------------------------------------------------------------------------- 1 | = Contributing to ClojureScript 2 | Rich Hickey 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | == Ways to Contribute 11 | 12 | There are many ways to make a meaningful contribution to the ClojureScript community: 13 | 14 | * Advocate for the use of ClojureScript in your organization 15 | * Use ClojureScript and share your experience via talks, blogs, etc 16 | * Start or join a local meetup 17 | * Help new ClojureScript users in Slack or other forums 18 | * Create or provide patches to open source libraries 19 | * Create or improve ClojureScript tools 20 | * Write guides or reference documentation for libraries 21 | * Write intros or getting started guides for tools 22 | * Create ClojureScript podcasts, screencasts, or videos 23 | * Give a talk at a conference 24 | * Write an article or book 25 | * Start a ClojureScript podcast 26 | * Test alpha or beta releases of ClojureScript on your code base and provide feedback 27 | 28 | === Editing this Site 29 | 30 | If you are writing a guide, making an event, or creating a resource, please 31 | consider contributing to this web site, clojurescript.org. All of the content is 32 | https://github.com/clojure/clojurescript-site[stored in GitHub] and pull requests and 33 | issues are accepted. For more information on how to contribute, see the page on 34 | <>. Every page has a link to the 35 | corresponding source file in the bottom right corner. If you have an idea for a 36 | new guide or updated documentation, please 37 | https://github.com/clojure/clojurescript-site/issues[file an issue] for discussion. 38 | 39 | == Reporting Problems and Requesting Enhancements 40 | 41 | The Clojure team provides a https://clojure.org/community/ask[forum] where users can ask questions, submit 42 | potential problems, and request enhancements to Clojure, ClojureScript, or 43 | Clojure contrib libraries. For all of these cases, please ask a question on the 44 | https://ask.clojure.org[forum]. Mark the question with tag `problem` for potential problems and 45 | `request` for enhancements. The community and core team will assess the issue 46 | and determine whether to file an issue in the jira tracker. If an issue is 47 | filed, the link will be added to the question and it will be tagged with `jira`. 48 | 49 | If you are looking to provide feedback on an issue in jira, please search the 50 | https://ask.clojure.org[forum] for the equivalent issue by title and add your 51 | feedback there as an "answer" instead. 52 | 53 | The development teams for these languages and libs will use the question votes 54 | to prioritize their work in jira towards the next release. 55 | 56 | == Making a contribution 57 | 58 | If you have a proposal for ClojureScript, please post it as a question on 59 | https://ask.clojure.org[https://ask.clojure.org] using the ClojureScript 60 | category and label it `request`. ClojureScript developers will help you 61 | determine whether this idea is a good fit for ClojureScript and a patch is 62 | wanted. If you would prefer to have a real time discussion before investing in 63 | a more considered proposal, the #cljs-dev https://clojurians.slack.com/[Clojurians Slack] 64 | channel is very active. 65 | 66 | If the ClojureScript developers indicate this is a useful thing to do, please 67 | follow the https://clojure.org/dev/dev[process] to become a contributor. This 68 | requires signing the Contributor Agreement and requesting access to the 69 | ClojureScript jira account. 70 | 71 | == Contributor Agreement 72 | 73 | Following the lead of other open source projects, the ClojureScript project 74 | requires contributors to jointly assign their copyright on contributed code. The 75 | https://na1.documents.adobe.com/public/esignWidget?wid=CBFCIBAA3AAABLblqZhCSXRbJ7T5RGvmMvmpg3CzvkF_RcpWXMnGWW_W9340ztJ3-ChQ0m18hA-d06ufD8Yk*[Contributor Agreement] (CA) gives Rich Hickey and the contributor joint copyright interests 76 | in the code: the contributor retains copyrights while also granting those rights 77 | to Rich Hickey as the open source project sponsor. 78 | 79 | The CA is derived from the Oracle Contributor Agreement (OCA), used for OpenJDK, 80 | Netbeans and OpenSolaris projects and others. There is a good 81 | https://www.oracle.com/technetwork/oca-faq-405384.pdf[OCA FAQ] answering many 82 | questions. 83 | 84 | The CA does not change the rights or responsibilities of the Clojure community 85 | under the https://opensource.org/license/epl-1-0/[Eclipse Public License 86 | (EPL)]. By executing the CA, contributors protect the Clojure code base, enable 87 | alternative licensing models, and protect the flexibility to adapt the project 88 | to the changing demands of the community. In order for the CA to be effective, 89 | the Clojure project must obtain an assignment for all contributions. Please 90 | review the CA for a complete understanding of its terms and conditions. By 91 | contributing source code or other material to Clojure, you represent that you 92 | have a CA with Rich Hickey for such contributions. In order to track 93 | contributors, you understand that your full name and username may be posted on a 94 | web page listing authorized contributors that is accessible via a public URL. 95 | 96 | == Instructions for submitting the agreement 97 | 98 | Fill out and submit the https://na1.documents.adobe.com/public/esignWidget?wid=CBFCIBAA3AAABLblqZhCSXRbJ7T5RGvmMvmpg3CzvkF_RcpWXMnGWW_W9340ztJ3-ChQ0m18hA-d06ufD8Yk*[Contributor Agreement] (an online e-form) 99 | 100 | Please see the https://clojure.org/community/contributing[Contributing] page for 101 | a collection of resources on tickets, builds, patches, source, and more. If 102 | you'd like to submit a patch, please follow these guidelines on the 103 | https://clojure.org/community/workflow[preferred process for submitting]. 104 | 105 | _**Many thanks for your contributions to ClojureScript!**_ 106 | -------------------------------------------------------------------------------- /content/community/custom-repls.adoc: -------------------------------------------------------------------------------- 1 | = Custom REPLs 2 | David Nolen 3 | 2016-08-01 4 | :type: guides 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | This page documents recent changes to requirements for custom REPLs that 11 | use the functionality provided in 12 | https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl.cljc[cljs.repl]. 13 | These changes have been made towards the goal of dramatically 14 | diminishing the start time of _all_ ClojureScript REPLs and simplifying 15 | the synchronization of REPL state with compiled source. This is 16 | accomplished by reusing the globally available compilation caching 17 | infrastructure. In fact it is currently possible to launch a REPL with 18 | `:output-dir` set to an existing compilation cache and incur no analysis 19 | or compilation. 20 | 21 | Under the new infrastructure all the builtin REPLs are capable of 22 | booting on modern hardware in a second or less. 23 | 24 | [[expectations]] 25 | === Expectations 26 | 27 | In order to boot REPLs as quickly as possible REPLs must implement the 28 | new 2-arg arity of `-setup` which take the typical compiler build 29 | options. In the past `-setup` was permitted to be asynchronous - this is 30 | no longer supported, REPLs must now compile and load cljs.core and all 31 | of its dependencies during `-setup`. In `-setup` REPLs should use the 32 | build options to cache compiled JavaScript and analysis information to 33 | the expected location. Note, while it is OK to stream compiled forms the 34 | user has entered this should be avoided at all costs for loading 35 | namespaces - REPLs should rely on the target environment to interpret 36 | `goog.require`. This has many benefits including precise source mapping 37 | information. 38 | 39 | The new Node.js REPL is a good example of the 40 | https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl/node.clj#L69[new 41 | pattern]. The Node.js REPL is short because it relies on the Node.js 42 | runtime itself to interpret `goog.require`. 43 | 44 | Examining `cljs.repl/load-file` and `cljs.repl/load-namespace` will 45 | clarify the new approach: 46 | 47 | * Given a namespace ensure that it's compiled. 48 | * Compute the `goog.addDependency` string for the file and evaluate it. 49 | * Emit `goog.require` statement for the namespace and evaluate it. 50 | 51 | REPLs should override the global `CLOSURE_IMPORT_SCRIPT` function to get 52 | custom `goog.require` behavior. 53 | 54 | [[eliminating-loaded-libs-tracking]] 55 | === Eliminating Loaded Libs tracking 56 | 57 | Under the new changes REPLs no longer need to bother with explicitly 58 | tracking loaded libs directly within their Clojure implementation. 59 | Instead, REPLs should arrange to ensure that the JavaScript evaluation 60 | environment honors `cljs.core/*loaded-libs*`, embedding the required 61 | logic in `CLOSURE_IMPORT_SCRIPT` if need be. 62 | 63 | History: This was only previously done because `goog.provide` throws if 64 | the namespace has already been loaded. This is a completely bogus error 65 | intended to teach "beginners". By monkey-patching `goog.isProvided_` to 66 | be a function that always returns false - the error can be suppressed. 67 | Again the Node.js REPL is a good example of such patching as well as 68 | honoring `*loaded-libs*` in the `CLOSURE_IMPORT_SCRIPT` implementation. 69 | 70 | [[special-functions]] 71 | === Special Functions 72 | 73 | All REPLs support several "special functions". Special functions must 74 | take the REPL environment, an analysis environment, the form, and 75 | (optionally) compiler build options. Out of the box `in-ns`, `require`, 76 | `load-file`, and `load-namespace` are provided. 77 | 78 | [[output]] 79 | === Output 80 | 81 | Custom REPLs should not call `println`, `print`, or `flush` directly, 82 | but should instead honor values associated with `:print`, 83 | `:print-no-newline`, and `:flush` in the `opts` (second argument) passed 84 | to `-setup`. Also note that the functions associated with `:print` and 85 | `:print-no-newline` take exactly one argument. 86 | 87 | [[source-mapping]] 88 | === Source Mapping 89 | 90 | All REPLs can now implement a new protocol in order to get source 91 | mapping support for "free". In the case of an `:exception` result from 92 | evaluation the REPL infrastructure will invoke `-parse-stacktrace` if 93 | the REPL evaluation environment satisfies `cljs.repl/IParseStacktrace`. 94 | The REPL evaluation environment will receive the original JavaScript 95 | stacktrace string, the entire original error value, as well as all build 96 | options passed into the REPL. The REPL evaluation environment may then 97 | return a canonical stacktrace which must take the form of: 98 | 99 | [source,clojure] 100 | ---- 101 | [{:function 102 | :file 103 | :line 104 | :column }*] 105 | ---- 106 | 107 | `:file` must be a URL style path (forward slashes) without a URI 108 | protocol relative to `:output-dir`. 109 | 110 | With 111 | https://github.com/clojure/clojurescript/commit/de15ba8f756457f9cb4f5758848147911665e56b[this 112 | commit], the contract has been relaxed slightly to accommodate 113 | REPL-defined functions: The `:file` value may begin with `<` to indicate 114 | that no source is present, and `"NO_SOURCE_FILE"` will be emitted in the 115 | trace. 116 | 117 | Custom REPLs may still want to further customize or control printing of 118 | stacktraces. A hook is provided, the REPL evaluation environment may 119 | implement `cljs.repl/IPrintStacktrace`. `-print-stacktrace` takes the 120 | mapped canonical stacktrace, the entire original error value, and all 121 | build options passed to the REPL. 122 | -------------------------------------------------------------------------------- /content/community/dev.adoc: -------------------------------------------------------------------------------- 1 | = Dev 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | [[contributing]] 11 | == Contributing 12 | 13 | ClojureScript is developed using the same 14 | https://clojure.org/dev/dev[Contributor Agreement and development 15 | process] as Clojure. 16 | 17 | [[dev-docs]] 18 | == Dev Docs 19 | 20 | * https://clojure.atlassian.net/browse/CLJS[Bugs and feature status] 21 | * <> 22 | * <> 23 | * <> 24 | * <> 25 | * <> 26 | * <> 27 | -------------------------------------------------------------------------------- /content/community/editing.adoc: -------------------------------------------------------------------------------- 1 | = Editing 2 | Alex Miller 3 | 2015-09-29 4 | :jbake-type: page 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | This page covers helpful Asciidoc editing tips for writing content on this site. It does not cover every feature of Asciidoc, just the ones that have come up most commonly while writing content on this site. 11 | 12 | == File metadata 13 | 14 | Every file should start with a metadata block that looks like this: 15 | 16 | ---- 17 | = Mechanical Computing 18 | Ada Lovelace 19 | 2015-12-31 20 | :jbake-type: page 21 | :toc: macro 22 | ---- 23 | 24 | The first lines indicate the title, author, and creation date. The last two lines are necessary boilerplate metadata attributes. 25 | 26 | == Headers 27 | 28 | == h2 29 | 30 | ---- 31 | == h2 32 | ---- 33 | 34 | === h3 35 | 36 | ---- 37 | === h3 38 | ---- 39 | 40 | ==== h4 41 | 42 | ---- 43 | ==== h4 44 | ---- 45 | 46 | == Text markup 47 | 48 | [cols="<*", options="header", role="table"] 49 | |=== 50 | | markup | effect 51 | | pass:[_italic_] | _italic_ 52 | | pass:[*bold*] | *bold* 53 | | pass:[_**italic and bold**_] | _**italic and bold**_ 54 | | pass:[`inline code`] | `inline code` 55 | | pass:[(C) (R) (TM)] | (C) (R) (TM) 56 | | pass:[-- ...] | -- ... 57 | | pass:[-> <- => <=] | -> <- => <= 58 | |=== 59 | 60 | To get a line break without a paragraph change, append + to the end of the line: 61 | 62 | ---- 63 | force + 64 | line break 65 | ---- 66 | 67 | force + 68 | line break 69 | 70 | '''' 71 | 72 | If you have many lines in a row that will need breaks you can prefix them with pass:[[%hardbreaks]]: 73 | 74 | ---- 75 | [%hardbreaks] 76 | first line 77 | second line 78 | ---- 79 | 80 | [%hardbreaks] 81 | first line 82 | second line 83 | 84 | '''' 85 | 86 | There are a number of ways to handle escaping in Asciidoc but one of the most helpful is to omit all formatting by using: 87 | 88 | ---- 89 | pass:[*ns*] 90 | ---- 91 | 92 | pass:[*ns*] 93 | 94 | == Links 95 | 96 | Create an anchor in a page: 97 | 98 | ---- 99 | [[dot]] 100 | ---- 101 | 102 | '''' 103 | 104 | Link to another internal page (note the trailing # after the page - this is required in our generator!): 105 | 106 | ---- 107 | <> 108 | ---- 109 | 110 | <> 111 | 112 | There is a bug in the parser used in the current version of JBake for links to a page in a parent directory. For example, to link to a page at ../reference/java_interop.adoc, you can use a link like this: 113 | 114 | ---- 115 | <> 116 | ---- 117 | 118 | This goes to a (fictitious) subdirectory xref, then back a directory, and then finally the path you wish to follow. While the choice of "xref" here is arbitrary, please use only this string so that we can more easily find and update these upward cross references later when there is a version that fixes this issue. 119 | 120 | '''' 121 | 122 | Link to an anchor in an internal page: 123 | 124 | ---- 125 | <> 126 | ---- 127 | 128 | <> 129 | 130 | '''' 131 | 132 | Link to an external page: 133 | 134 | ---- 135 | https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defn[defn] 136 | ---- 137 | 138 | https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defn[defn] 139 | 140 | == Images 141 | 142 | Images should be placed in the assets/images/content directory in a subdirectory corresponding to the page location. 143 | 144 | Reference the image in a page as follows: 145 | 146 | ---- 147 | image::/images/content/reference/transducers/xf.png[Nested transformations] 148 | ---- 149 | 150 | image::/images/content/reference/transducers/xf.png[Nested transformations] 151 | 152 | == Code blocks 153 | 154 | You can insert a Clojure formatted code block as follows: 155 | 156 | .... 157 | [source,clojure] 158 | ---- 159 | (defn hey 160 | [] 161 | (println "hey")) 162 | ---- 163 | .... 164 | 165 | [source,clojure] 166 | ---- 167 | (defn hey 168 | [] 169 | (println "hey")) 170 | ---- 171 | 172 | == Lists 173 | 174 | There are a lot of options for creating lists. Only the most common ones are shown here: 175 | 176 | Bulleted lists: 177 | 178 | ---- 179 | * first 180 | * second 181 | ** nested 182 | *** more nested 183 | ---- 184 | 185 | * first 186 | * second 187 | ** nested 188 | *** more nested 189 | 190 | Ordered lists: 191 | 192 | ---- 193 | . a 194 | . b 195 | .. b.1 196 | ... b.1.a 197 | ---- 198 | 199 | . a 200 | . b 201 | .. b.1 202 | ... b.1.a 203 | 204 | Mixed lists: 205 | 206 | ---- 207 | * a 208 | . a.1 209 | . a.2 210 | * b 211 | . b.1 212 | . b.2 213 | ---- 214 | 215 | * a 216 | . a.1 217 | . a.2 218 | * b 219 | . b.1 220 | . b.2 221 | 222 | Use the line break advice from the text formatting section to create lists with multi-line items. 223 | 224 | == Tables 225 | 226 | Tables are another large Asciidoc topic with extensive formatting options. This is a basic table example however: 227 | 228 | ---- 229 | [options="header"] 230 | |=== 231 | | col1 | col2 232 | | a | b 233 | | b | c 234 | |=== 235 | ---- 236 | 237 | [options="header"] 238 | |=== 239 | | col1 | col2 240 | | a | b 241 | | b | c 242 | |=== 243 | 244 | == Other 245 | 246 | Horizontal rule: 247 | 248 | ---- 249 | '''' 250 | ---- 251 | 252 | Insert table of contents, which should generally be done at the top of your file (the page template will position this appropriately): 253 | 254 | ---- 255 | toc::[] 256 | ---- 257 | 258 | 259 | == More resources 260 | 261 | Asciidoc is an extensive language and there is likely some way to do anything you want to do. Below are some more Asciidoc resources to answer more advanced questions. 262 | 263 | * https://powerman.name/doc/asciidoc[Asciidoc cheat sheet] 264 | * https://asciidoctor.org/docs/user-manual[Asciidoctor user manual] 265 | -------------------------------------------------------------------------------- /content/community/license.adoc: -------------------------------------------------------------------------------- 1 | = License 2 | Rich Hickey 3 | 2015-01-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | The use and distribution terms for this software are covered by the https://opensource.org/licenses/eclipse-1.0.php[Eclipse Public License 1.0], which can be found in the file epl-v10.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound by the terms of this license. You must not remove this notice, or any other, from this software. 11 | -------------------------------------------------------------------------------- /content/community/patches.adoc: -------------------------------------------------------------------------------- 1 | = Patches 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | [[creating-patches]] 11 | === Creating patches 12 | 13 | Make a branch off master and write the code for the patch and commit it. 14 | Please write the commit message starting with `CLJS-NNNN: TICKET TITLE`, 15 | followed by an empty line, followed by a few sentences explaining the 16 | changes. Please squash multiple commits into a single commit. Then 17 | produce the patch with the following: 18 | 19 | [source,bash] 20 | ---- 21 | git format-patch master --stdout > CLJS-NNNN.patch 22 | ---- 23 | 24 | [[testing-patches]] 25 | === Testing patches 26 | 27 | In order to test ClojureScript patches in your own project, apply the 28 | patch to a local clone of the ClojureScript repo. Run `script/build`, 29 | this will install a version of ClojureScript - note the version number. 30 | Change your projects `:dependencies` to use this version number and 31 | confirm the patch works for you. 32 | 33 | [[submitting-patches]] 34 | === Submitting patches 35 | 36 | Attach `CLJS-NNNN.patch` to the associated JIRA ticket, providing 37 | additional commentary that may be useful for understanding the patch. 38 | 39 | If submitting follow-on patches in order to address comments raised 40 | during review or defects found in a patch, name them `CLJS-NNNN-2.patch`, 41 | `CLJS-NNNN-3.patch`, and so on. Subsequent patches should be stand-alone 42 | (squashed and not dependent on earlier patches). 43 | 44 | Edit the ticket's Patch field to indicate either "Code" or "Code and 45 | Test". This makes it easier for others to find patches in need of review 46 | (appearing in the https://clojure.atlassian.net/issues/?filter=10017[CLJS 47 | Screenable] preset filter). 48 | 49 | [[a-note-about-patches-for-windows-files]] 50 | === A note about patches for Windows files 51 | 52 | Patches that modify files with Windows line endings may fail to apply. Running `git am --keep-cr < /path/to/CLJS-NNNN.patch` will generally apply the patch if it would otherwise apply cleanly (*i.e.* no merge conflicts). 53 | -------------------------------------------------------------------------------- /content/community/reporting-bootstrap-issues.adoc: -------------------------------------------------------------------------------- 1 | = Reporting Bootstrap Issues 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | [[ticket-entry]] 11 | == Ticket Entry 12 | 13 | Please enter issues with self-hosted / bootstrapped ClojureScript 14 | 15 | * marked as having Minor priority 16 | * title prefixed with "Self-host: " 17 | * marked with `bootstrap` label 18 | 19 | [[minimal-repro]] 20 | == Minimal Repro 21 | 22 | Do not rely on downstream bootstrapped environments to report or 23 | demonstrate issues. 24 | 25 | Oftentimes, a new unit test can be written that fails when 26 | `script/test-self-parity` is run. (This runs the compiler unit tests, 27 | but in a bootstrap environment). 28 | 29 | Otherwise, reproduction steps generally need to involve minimal code 30 | that exercises `cljs.js`, demonstrating the issue. 31 | 32 | Frequently it is possible to do this with a couple of lines in a REPL. 33 | Here is an example exercising the `cljs.js/eval-str` API by simply 34 | issuing a couple forms in the shipping Node REPL: 35 | 36 | [source,bash] 37 | ---- 38 | $ clj -M -m cljs.main cljs.repl.node 39 | To quit, type: :cljs/quit 40 | cljs.user=> (require 'cljs.js) 41 | nil 42 | cljs.user=> (cljs.js/eval-str (cljs.js/empty-state) 43 | "(+ 1 2)" nil {:eval cljs.js/js-eval :context :expr} prn) 44 | {:ns cljs.user, :value 3} 45 | nil 46 | ---- 47 | 48 | For more complex situations, reproduction could involve additional code, 49 | or even a new self-host unit test that exhibits the problem. Information 50 | on self-host unit tests is <>. 51 | -------------------------------------------------------------------------------- /content/community/reporting-issues.adoc: -------------------------------------------------------------------------------- 1 | = Reporting Issues 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | To report an issue please file a question on https://ask.clojure.org[ask.clojure.org] under the ClojureScript category and tag it with `problem`. CLJS developers can assess and determine whether it is an issue. If needed, they can file a ticket in the https://clojure.atlassian.net/browse/CLJS[ClojureScript issue tracker]. 11 | 12 | It's important that before submitting any issue that you have a thorough 13 | understanding of the <> first. Even if you are an 14 | experienced ClojureScript developer this is required reading. 15 | 16 | It's helpful, but not essential, to first check the 17 | https://clojure.atlassian.net/browse/CLJS[existing bug reports], the 18 | https://groups.google.com/forum/#!forum/clojurescript[mailing list], or 19 | the Freenode #clojurescript IRC channel or Slack channels and ensure 20 | that the issue hasn't been reported before. 21 | 22 | Also, it can be helpful to ensure that you are running the latest 23 | released version of ClojureScript. Also, checking against ClojureScript 24 | master is prudent—frequently when bugs are found, fixes are quickly 25 | committed (see instructions below). 26 | 27 | It is essential, however, to report the bug using ClojureScript only. 28 | Downstream tooling often interacts with the ClojureScript compiler in 29 | non-trivial ways, and the best way to isolate the issue to ClojureScript 30 | is to remove them from the report altogether. 31 | 32 | Please report issues by building the uberjar from master and using this 33 | to verify the issue. Using https://clojurescript.org/reference/repl-and-main[`cljs.main`] 34 | with this uberjar to create a minimal repro is ideal. Alternatively, 35 | using https://clojure.org/guides/getting_started[`clj`] and `deps.edn` is 36 | acceptable. Do not use any other 3rd party tooling (Maven, 37 | Leiningen, Boot). When creating issues please add all relevant 38 | instructions and code to reproduce to the ticket directly or via 39 | additional comments. Please do not attach projects, links to projects, 40 | links to gists / pastebins, or zips. 41 | 42 | [NOTE] 43 | ==== 44 | Bootstrap issues may require special consideration. Please see <> for more details. 45 | ==== 46 | 47 | [[building-the-uberjar-from-master]] 48 | === Building the uberjar from master 49 | 50 | Make a checkout of the ClojureScript repository. From the root of the 51 | project run the following: 52 | 53 | [source,bash] 54 | ---- 55 | ./script/uberjar 56 | ---- 57 | 58 | This will create `target/cljs.jar`. 59 | 60 | [[installing-from-master]] 61 | === Installing from master 62 | 63 | When verifying issues it may be useful to first check that the issue has 64 | not already been resolved in master. __Do not report issues using this 65 | method, it's only for convenience when verifying master yourself__. Make 66 | a checkout of the ClojureScript repository. From the root of the project 67 | run the following: 68 | 69 | [source,bash] 70 | ---- 71 | ./script/build 72 | ---- 73 | 74 | This will install ClojureScript into your local Maven. Make note of the 75 | version when it scrolls by. Use this as appropriate for your tooling. 76 | 77 | [[pinpointing-regressions-with-git-bisect]] 78 | === Pinpointing Regressions with git bisect 79 | 80 | If you've discovered a regression, it is helpful to identify information 81 | regarding the first bad commit when reporting issues. This is easy to do by 82 | first depending on a checkout of ClojureScript as a local root dependency and 83 | then using `git bisect`. 84 | 85 | For this example, let's say you've discovered a regression that is reproducible 86 | directly in the REPL (variations on the below can be employed if not). 87 | 88 | First checkout ClojureScript master and `cd` to the top of the checkout tree. 89 | 90 | Assuming you can reproduce the issue on master, but that things worked with 91 | ClojureScript 1.10.748, issue these commands at the top of the checkout tree: 92 | 93 | [source,bash] 94 | ---- 95 | git bisect start 96 | git bisect bad HEAD 97 | git bisect good r1.10.748 98 | ---- 99 | 100 | Then (in another directory) start up a REPL against the current state of the 101 | checkout tree by issuing: 102 | 103 | [source,bash] 104 | ---- 105 | clj -Srepro -Sdeps '{:deps {org.clojure/clojurescript {:local/root "//clojurescript"}}}' -m cljs.main -r 106 | ---- 107 | 108 | Test to see if you can reproduce the issue in the REPL and then exit the REPL. 109 | 110 | If you couldn't reproduce the problem, issue this in the ClojureScript 111 | checkout tree: 112 | 113 | [source,bash] 114 | ---- 115 | git bisect good 116 | ---- 117 | 118 | Or, if you were able to reproduce the problem: 119 | 120 | [source,bash] 121 | ---- 122 | git bisect bad 123 | ---- 124 | 125 | If the bisect is complete, `git` will indicate that a certain commit hash 126 | "is the first bad commit." Copy all of this text for JIRA. 127 | 128 | Otherwise restart the REPL and repeat the above steps until done. 129 | 130 | When finished, you can issue this to restore your ClojureScript checkout: 131 | 132 | [source,bash] 133 | ---- 134 | git bisect reset 135 | ---- 136 | -------------------------------------------------------------------------------- /content/community/resources.adoc: -------------------------------------------------------------------------------- 1 | = Community Resources 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | [[tutorials]] 11 | == Tutorials 12 | 13 | * https://github.com/magomimmo/modern-cljs[modern-cljs] 14 | * https://funcool.github.io/clojurescript-unraveled/[ClojureScript 15 | Unraveled] (book) 16 | * https://clojurescriptmadeeasy.com/[ClojureScript Made Easy] (blog) 17 | * https://github.com/bhauman/lein-figwheel/wiki/Quick-Start[Getting 18 | started with Figwheel] 19 | * https://github.com/vvvvalvalval/reagent-phonecat-tutorial/wiki[Reagent 20 | Phonecat] : official AngularJS 1.X tutorial, re-written for 21 | ClojureScript + Reagent. 22 | 23 | [[learning-tools]] 24 | == Learning Tools 25 | 26 | * https://replete-repl.org[Replete] ClojureScript REPL iOS, macOS, and Android app 27 | * https://planck-repl.org[Planck] Stand-alone ClojureScript REPL for macOS and Linux 28 | * https://github.com/priyatam/replify[Replify] Standalone Clojurescript 29 | REPL and minimalist build tool 30 | * https://github.com/princejwesley/Mancy[Mancy] Electron based NodeJS 31 | REPL with ClojureScript Support + (Data Visualisation, Transpiled JS 32 | View & more…) 33 | 34 | [[online-clojurescript-repls]] 35 | == Online Clojurescript REPLs 36 | 37 | * https://app.klipse.tech[KLIPSE] 38 | * https://clojurescript.io/[clojurescript.io] 39 | * https://clojurescript.net/[clojurescript.net] 40 | 41 | [[getting-help]] 42 | == Getting Help 43 | 44 | [[chat]] 45 | === Chat 46 | 47 | * IRC: `#clojurescript` on https://freenode.net/[freenode.net] 48 | * Slack: `#clojurescript` on https://clojurians.slack.com/[Clojurians Slack] (http://clojurians.net/[get an invite here]) 49 | ** searchable chat logs can be found https://clojurians.zulipchat.com/#narrow/stream/180378-slack-archive/topic/clojurescript[here], and https://clojurians-log.clojureverse.org/[here] 50 | * Zulip: `#clojurescript` on https://clojurians.zulipchat.com/#narrow/stream/151762-clojurescript[Clojurians Zulip Chat] 51 | 52 | [[mailing-lists]] 53 | === Mailing Lists 54 | 55 | * https://groups.google.com/group/clojurescript[ClojureScript user mailing list] 56 | * https://groups.google.com/group/clojure[Clojure mailing list] 57 | 58 | [[feedback]] 59 | === Feedback 60 | 61 | ClojureScript does not take pull requests. Please follow the links below 62 | to contribute to ClojureScript. 63 | 64 | * https://clojure.atlassian.net/browse/CLJS[Bug Reports] 65 | * https://archive.clojure.org/design-wiki/display/design/Home.html[Design Docs archive] 66 | * https://groups.google.com/group/clojure-dev[Dev Mailing List] - 67 | membership restricted to those who have submitted a signed 68 | https://clojure.org/dev/contributor_agreement[Clojure CA] (Contributor Agreement) 69 | * https://groups.google.com/group/clojurescript[ClojureScript Mailing List] 70 | * Become a https://clojure.org/dev/contributor_agreement[Contributor] 71 | 72 | -------------------------------------------------------------------------------- /content/community/running-tests.adoc: -------------------------------------------------------------------------------- 1 | = Running the Tests 2 | David Nolen 3 | 2016-08-01 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | [[testing-the-compiler-infrastructure]] 11 | == Testing the Compiler Infrastructure 12 | 13 | [source,bash] 14 | ---- 15 | lein test 16 | ---- 17 | 18 | Will run the tests for the analyzer, compiler, and closure components. 19 | 20 | [[testing-javascript-engines]] 21 | == Testing JavaScript Engines 22 | 23 | How to setup the important JavaScript runtimes. 24 | 25 | [[google-v8]] 26 | === Google V8 27 | 28 | Follow https://v8.dev/docs/build[Google V8 checkout and build instructions]. 29 | 30 | Set the V8_HOME environment variable to the path where https://v8.dev/docs/d8[d8] was built, for example: 31 | 32 | `export V8_HOME="$HOME/v8/out/x64.release"` 33 | 34 | Verify via: 35 | 36 | `echo quit | $V8_HOME/d8` 37 | 38 | [[spidermonkey]] 39 | === Mozilla SpiderMonkey 40 | 41 | Get the JavaScript shell (jsshell) from 42 | https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/. 43 | Set your SPIDERMONKEY_HOME environment variable to installation location. 44 | 45 | Verify via: 46 | 47 | `$SPIDERMONKEY_HOME/js --version` 48 | 49 | [[javascriptcore]] 50 | === WebKit JavaScriptCore 51 | 52 | On macOS we test with JavaScriptCore. JavaScriptCore (jsc) should be on your system, but needs to 53 | be added to your `PATH` environment variable so that it will be found, for example: 54 | 55 | `export PATH="$PATH:/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources"` 56 | 57 | Verify that `jsc` brings up a prompt. 58 | 59 | 60 | [[nashorn]] 61 | === Java Nashorn 62 | 63 | Setup the `$NASHORN_HOME` environment variable so that 64 | 65 | `$NASHORN_HOME/jjs` 66 | 67 | prompts a JavaScript Console. Nashorn is usually under `$JAVA_HOME/bin`, 68 | so you can write: 69 | 70 | `export NASHORN_HOME="$JAVA_HOME/bin"` 71 | 72 | Verify via: 73 | 74 | `echo 'quit()' | $NASHORN_HOME/jjs -fv` 75 | 76 | [[graalvm]] 77 | === Oracle GraalVM 78 | 79 | Get GraalVM from https://www.graalvm.org. 80 | Set your GRAALVM_HOME environment variable so that `$GRAALVM_HOME/js` executes Graal.js. 81 | 82 | Verify via: 83 | 84 | `$GRAALVM_HOME/js --version` 85 | 86 | 87 | [[chakracore]] 88 | === Microsoft ChakraCore 89 | 90 | Get ChakraCore from https://github.com/Microsoft/ChakraCore/releases. 91 | Set your CHAKRACORE_HOME environment variable so that `$CHAKRACORE_HOME/ch` executes ChakraCore. 92 | 93 | Verify via: 94 | 95 | `$CHAKRACORE_HOME/ch -version` 96 | 97 | [[setting-up-dependencies]] 98 | === Setting up dependencies 99 | 100 | [source,bash] 101 | ---- 102 | ./script/bootstrap 103 | ---- 104 | 105 | [[running-the-tests]] 106 | === Running the tests 107 | 108 | [source,bash] 109 | ---- 110 | ./script/test 111 | ---- 112 | 113 | Will run tests for each JavaScript runtime that you setup as described above, runtimes that you did not setup will be skipped. 114 | 115 | [[running-bootstrapped-clojurescript-tests]] 116 | === Running bootstrapped ClojureScript tests 117 | 118 | If you have Node.js installed, you can run the bootstrapped 119 | ClojureScript test suite (located at 120 | `src/test/self/self_host/test.cljs`): 121 | 122 | [source,bash] 123 | ---- 124 | ./script/test-self-host 125 | ---- 126 | 127 | You can also build and run the ClojureScript compiler test suite in 128 | bootstrapped mode within Node.js by running 129 | 130 | [source,bash] 131 | ---- 132 | ./script/test-self-parity 133 | ---- 134 | 135 | [[running-clojurescript-cli-tests]] 136 | === Running ClojureScript CLI (`cljs.main`) tests 137 | 138 | You can run tests exercising the ClojureScript CLI by running 139 | 140 | [source,bash] 141 | ---- 142 | ./script/test-cli repl-env [repl-env-opts-edn] 143 | ---- 144 | 145 | where `repl-env` is any of the built-in REPL environments (`node`, `browser`, _etc._). This will be passed to `cljs.main` 's `-re` option. 146 | 147 | Note that testing with `graaljs` REPL environment requires GRAALVM_HOME to be found early in your PATH. You can test via: 148 | [source,bash] 149 | ---- 150 | (export PATH="$GRAALVM_HOME:$PATH"; ./script/test-cli graaljs) 151 | ---- 152 | 153 | You can also specify a non-built-in REPL environment, but you would have to revise `script/test-cli` to include the downstream REPL environment on the classpath. You can also pass optional `repl-env-opts-edn`, which will be passed to `cljs.main` 's `-ro` option. 154 | 155 | [[dont-forget]] 156 | === Don't forget the Browser REPL 157 | 158 | It is important to make sure that the Browser REPL hasn't accidentally been broken. 159 | 160 | You may have already run tests against the browser REPL via `./script/test-cli browser`. If not, now is a good time to do so. 161 | Note: It is normal for this test to launch plenty of browser windows/tabs. 162 | 163 | In addition, you might only be comfortable after some manual verification - if only to try a sanity `(js/alert "Hello CLJS!")`: 164 | 165 | . You can launch a browser REPL by running `clj -M -m cljs.main` from the clojurescript project root dir. 166 | . Or from a new empty dir, create a `deps.edn` that points to your <> replacing `1.10.123` 167 | with your local version: 168 | + 169 | [source,clojure] 170 | ---- 171 | {:deps {org.clojure/clojurescript {:mvn/version "1.10.123"}}} 172 | ---- 173 | and then from this dir, run `cljs -m cljs.main`. 174 | -------------------------------------------------------------------------------- /content/guides/code-splitting.adoc: -------------------------------------------------------------------------------- 1 | = Code Splitting 2 | David Nolen 3 | 2017-07-10 4 | :type: guides 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | *This guide requires ClojureScript 1.10.238 or later and assumes 11 | familiarity with the <>*. 12 | 13 | As client applications become larger it becomes desirable to load only the code 14 | actually required to run a particular logical screen. Previously ClojureScript 15 | `:modules` compiler option permitted such code splitting, but this feature only 16 | worked under `:advanced` compilation and users would still have to manage 17 | loading these splits. `:modules` also required manual explicit placement of many 18 | entries to produce optimal splits otherwise dependencies would get moved to 19 | `:cljs-base`. 20 | 21 | All of these issues are now addressed directly in ClojureScript. This guide will 22 | walk you through code splitting a simple project and demonstrate these new 23 | enhancements. 24 | 25 | === Make a Simple Project 26 | 27 | Create a project folder: 28 | 29 | [source,bash] 30 | ``` 31 | mkdir -p hello-modules 32 | cd hello-modules 33 | mkdir src 34 | ``` 35 | 36 | Create a `deps.edn` file that looks like the following: 37 | 38 | [source,clojure] 39 | ``` 40 | {:deps {org.clojure/clojurescript {:mvn/version "1.11.54"}}} 41 | ``` 42 | 43 | Create a `build.edn` file that looks like the following: 44 | 45 | [source,clojure] 46 | ``` 47 | {:output-dir "out" 48 | :asset-path "/out" 49 | :browser-repl false 50 | :modules {:foo {:entries #{foo.core} 51 | :output-to "out/foo.js"} 52 | :bar {:entries #{bar.core} 53 | :output-to "out/bar.js"}}} 54 | ``` 55 | 56 | Now make an `index.html` file: 57 | 58 | [source,html] 59 | ``` 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | ``` 68 | 69 | === The Sources 70 | 71 | Create the `foo.core` namespace: 72 | 73 | [source,bash] 74 | ``` 75 | mkdir -p src/foo 76 | touch src/foo/core.cljs 77 | ``` 78 | 79 | Edit this file to look like the following: 80 | 81 | [source,clojure] 82 | ``` 83 | (ns foo.core 84 | (:require [goog.dom :as gdom] 85 | [goog.events :as events] 86 | [cljs.loader :as loader]) 87 | (:import [goog.events EventType])) 88 | 89 | (println "I'm foo!") 90 | 91 | (events/listen (gdom/getElement "button") EventType.CLICK 92 | (fn [e] 93 | (loader/load :bar 94 | (fn [] 95 | ((resolve 'bar.core/woz)))))) 96 | 97 | (loader/set-loaded! :foo) 98 | ``` 99 | 100 | Notice the unfamiliar namespace `cljs.loader`. This namespace provides a Google 101 | Closure ModuleManager singleton to manage the loading of code splits. This 102 | manager will be initialized with whatever module graph you have defined in 103 | `:modules`. 104 | 105 | When the user clicks the button we load the `:bar` module and invoke a function 106 | that exists in the `bar.core` namespace. Notice that we use `resolve`. This is 107 | because we cannot directly call something we never required. If we tried to do 108 | this without `resolve` the ClojureScript compiler would emit an undeclared var 109 | warning during compilation. 110 | 111 | Finally, note that it is necessary to manually mark a module as loaded via 112 | `cljs.loader/set-loaded!`. Without this dependencies may be loaded multiple 113 | times which may lead to unpredictable behavior. 114 | 115 | Create the `bar.core` namespace: 116 | 117 | [source,bash] 118 | ``` 119 | mkdir -p src/bar 120 | touch src/bar/core.cljs 121 | ``` 122 | [source,clojure] 123 | 124 | ``` 125 | (ns bar.core 126 | (:require [cljs.loader :as loader])) 127 | 128 | (println "I'm bar!") 129 | 130 | (defn woz [] 131 | (println "WOZ!")) 132 | 133 | (loader/set-loaded! :bar) 134 | ``` 135 | 136 | === Build the Project 137 | 138 | Build your project and start the builtin HTTP server: 139 | 140 | [source,bash] 141 | ``` 142 | clj -M -m cljs.main -v -co build.edn -c -s 143 | ``` 144 | 145 | Navigate to http://localhost:9000/index.html. 146 | 147 | Click the button. You will see that the `:bar` module gets loaded and the 148 | function in the other namespace gets invoked. 149 | 150 | === Release Builds 151 | 152 | Build your project: 153 | 154 | [source,bash] 155 | ``` 156 | clj -M -m cljs.main -co build.edn -O advanced -c -s 157 | ``` 158 | 159 | Navigate to http://localhost:9000/index.html. Your application should function 160 | correctly even though advanced compiled. 161 | 162 | Change the `foo.core` to take a new require like `cljs.reader`. Rebuild. 163 | 164 | You should see that `cljs.reader` gets moved into the `:foo` module but not 165 | `:bar`. 166 | 167 | If you examine the split files in `out` you will see that `foo.js` is larger 168 | than `bar.js`. 169 | 170 | === Additional Notes 171 | 172 | Because the code in splits is running in JavaScript's global scope, sometimes it 173 | may interfere with other JavaScript loaded on the same page (i.e. analytics), 174 | which may result in unpredictable behaviour. If this is a problem for your 175 | application prefix all variables in generated JavaScript by specifiyng 176 | `:rename-prefix` compiler option. 177 | -------------------------------------------------------------------------------- /content/guides/externs.adoc: -------------------------------------------------------------------------------- 1 | = Externs 2 | David Nolen 3 | 2017-01-22 4 | :type: guides 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | *This guide requires ClojureScript 1.10.238 or later and assumes 13 | familiarity with the <>*. 14 | 15 | This page documents how to write externs for third party JavaScript libraries 16 | that do not conform to Google Closure Compiler conventions 17 | https://developers.google.com/closure/compiler/docs/limitations. 18 | 19 | [[motivation]] 20 | == Motivation 21 | 22 | Many useful libraries cannot go through Google Closure Compiler advanced 23 | compilation. Thus they cannot be a part of the build and are considered 24 | "foreign". Still Closure must know something about these libraries, otherwise 25 | properties may be unintentionally renamed. Unfortunately, often this accidental 26 | renaming won't be apparent until the least opportune time - production. 27 | 28 | For libraries that already have mature externs this type of mistake is easily 29 | avoided. However, this requirement adds an incredible amount of friction to the 30 | adoption of newer or less popular but equally useful libraries. With the arrival 31 | of externs inference, the ClojureScript compiler can now automatically generate 32 | missing externs as well as greatly aid the process of writing comprehensive 33 | externs. 34 | 35 | [[externs-inference]] 36 | == Externs Inference 37 | 38 | Imagine that we have specified a foreign library `some.fooLib`. We would like 39 | to write interop against this library but have certainty that either the correct 40 | externs will be automatically generated or the compiler will notify us of 41 | externs we must additionally supply. 42 | 43 | To enable externs inference, we specify the `:infer-externs true` in our compiler 44 | configuration. 45 | 46 | Create a `build.edn` file with the following content: 47 | 48 | [source,clojure] 49 | ---- 50 | {:main my-project.core 51 | :output-to "out/main.js" 52 | :output-dir "out" 53 | :optimizations :none 54 | :infer-externs true}) 55 | ---- 56 | 57 | However this alone isn't enough to have the compiler generate warnings around 58 | externs. Because of the large number of libraries written before this 59 | feature existed, we cannot enable this capability in a global way. Instead there is a new 60 | file local compiler flag `\*warn-on-infer*` which is somewhat analogous to 61 | `\*warn-on-reflection*` in Clojure. Once set the compiler 62 | will warn for the remainder of the file anytime it cannot determine the types 63 | involved in a dot form, whether property access or method invocation. 64 | 65 | [source,clojure] 66 | ---- 67 | (ns my-project.core 68 | (:require [some.fooLib])) 69 | 70 | (set! *warn-on-infer* true) 71 | 72 | (defn wrap-baz [x] 73 | (.baz x)) 74 | ---- 75 | 76 | The above code would trigger a warning message: 77 | 78 | ---- 79 | Cannot infer target type in expression (.baz x) ... 80 | ---- 81 | 82 | We simply need to type-hint `x` with the foreign type for this interop call: 83 | 84 | [source,clojure] 85 | ---- 86 | (ns my-project.core 87 | (:require [some.fooLib])) 88 | 89 | (set! *warn-on-infer* true) 90 | 91 | (defn wrap-baz [^js/Foo.Bar x] 92 | (.baz x)) 93 | ---- 94 | 95 | The compiler now has enough information to automatically generate the required 96 | externs. When you run your build you will see a new file in your output 97 | directory `inferred_externs.js`. If you examine its contents it will probably 98 | look similar to the following: 99 | 100 | [source,javascript] 101 | ---- 102 | var Foo = {}; 103 | Foo.Bar = function() {}; 104 | Foo.Bar.prototype.baz = function() {}; 105 | ---- 106 | 107 | Quickly integrating foreign JavaScript libraries without complete externs is now 108 | considerably easier and less error prone. 109 | 110 | In some cases you may still want to write externs or you may be a consumer of a 111 | popular JavaScript library with mature externs and you would like a bit more 112 | validation. The following section describes an additional useful feature 113 | provided by externs inference. 114 | 115 | [[return-types]] 116 | == Return Types 117 | 118 | Local type hints go a long way to automating the process of writing externs. 119 | However, for interop heavy code this will lead to a lot of type hinting 120 | particularly for the return values of commonly used functions. In this case it's 121 | probably better to provide the externs file. Even here the ClojureScript 122 | compiler can ease the process: 123 | 124 | [source,clojure] 125 | ---- 126 | (ns my-project.core 127 | (:require [some.fooLib])) 128 | 129 | (set! *warn-on-infer* true) 130 | 131 | (defn my-fn [^js/Foo.Bar x] 132 | (let [z (.baz x)] 133 | (.-wozz z))) 134 | ---- 135 | 136 | Imagine that our externs file looks something like the following: 137 | 138 | [source,javascript] 139 | ---- 140 | var Foo = {}; 141 | /** 142 | * @constructor 143 | */ 144 | Foo.Bar = function() {}; 145 | Foo.Bar.prototype.baz = function() {}; 146 | /** 147 | * @constructor 148 | */ 149 | Foo.Boo = function() {}; 150 | Foo.Boo.prototype.woz = function() {}; 151 | ---- 152 | 153 | However this isn't sufficient for knowing the type of `z` in the ClojureScript 154 | program. The ClojureScript compiler will issue the following warning: 155 | 156 | ---- 157 | WARNING: Adding extern to Object for property wozz due to ambiguous expression (. z -wozz) ... 158 | ---- 159 | 160 | We need to add the return type information to the externs file: 161 | 162 | [source,javascript] 163 | ---- 164 | var Foo = {}; 165 | /** 166 | * @constructor 167 | */ 168 | Foo.Bar = function() {}; 169 | /** 170 | * @return {Foo.Boo} <-- CHANGED 171 | */ 172 | Foo.Bar.prototype.baz = function() {}; 173 | /** 174 | * @constructor 175 | */ 176 | Foo.Boo = function() {}; 177 | Foo.Boo.prototype.woz = function() {}; 178 | ---- 179 | 180 | Touching your source file and re-running build will result in a different 181 | warning: 182 | 183 | ---- 184 | WARNING: Cannot resolve property wozz for inferred type js/Foo.Boo in expression (. z -wozz) 185 | ---- 186 | 187 | As we can see the ClojureScript used the return type information to clarify 188 | the problem. 189 | -------------------------------------------------------------------------------- /content/guides/faq.adoc: -------------------------------------------------------------------------------- 1 | = Frequently Asked Questions 2 | David Nolen 3 | 2016-08-01 4 | :type: guides 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | == Builds 13 | 14 | [[slow_dev]] 15 | **<>** 16 | 17 | Make sure that your development classpath does not unnecessarily include test directories. ClojureScript now always recompiles child namespaces and changing a file could easily unintentionally trigger recompilation of all of your tests. Passing `:verbose true` is a simple way to check that the compiler isn't compiling more than it should. 18 | -------------------------------------------------------------------------------- /content/guides/guides.adoc: -------------------------------------------------------------------------------- 1 | = Guides 2 | Alex Miller 3 | 2015-11-25 4 | :type: guides 5 | :toc: macro 6 | 7 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 8 | 9 | * <> 10 | * <> 11 | * <> 12 | * <> 13 | * <> 14 | * <> 15 | * <> 16 | * <> 17 | * <> 18 | * <> 19 | * <> 20 | -------------------------------------------------------------------------------- /content/guides/native-executables.adoc: -------------------------------------------------------------------------------- 1 | = Native executables 2 | Craig Andera 3 | 2016-09-23 4 | :type: guides 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | This guide illustrates how to produce native executables 11 | from ClojureScript source. The basic idea is to produce a 12 | JavaScript file using the ClojureScript compiler, and then use a 13 | Node.js tool called https://github.com/jaredallard/nexe[nexe] to 14 | compile that into an executable. The resulting file can be run 15 | without requiring a node install on the target machine, which can 16 | be handy. 17 | 18 | nexe works by compiling the v8 engine into an exe that also 19 | contains your Javascript. So, strictly speaking, your program 20 | itself is not being compiled ahead of time. But if what you're 21 | after is the packaging convenience of an EXE, this is still pretty 22 | handy. 23 | 24 | Setup: 25 | 26 | [source,bash] 27 | ---- 28 | # Install node and nexe 29 | brew install node 30 | npm install nexe -g 31 | ---- 32 | 33 | Make a little hello world file: 34 | 35 | [source,bash] 36 | ---- 37 | mkdir -p /tmp/nexe-test/src 38 | cd /tmp/nexe-test 39 | cat > src/hello.cljs < console.log(val)); 23 | ---- 24 | 25 | *ClojureScript:* 26 | [source,clojure] 27 | ---- 28 | (.then (js/Promise.resolve 42) 29 | #(js/console.log %)) 30 | ---- 31 | 32 | However, chained promise methods in ClojureScript results in cascading code. 33 | Using the https://cljs.github.io/api/cljs.core/#-GT[thread-first macro] we can can get back to more 34 | elegant code. 35 | 36 | *JavaScript:* 37 | [source,clojure] 38 | ---- 39 | Promise.resolve(42) 40 | .then(val => console.log(val)) 41 | .catch(err => console.log(err)) 42 | .finally(() => console.log('cleanup')); 43 | ---- 44 | 45 | *ClojureScript:* 46 | [source,javascript] 47 | ---- 48 | (.finally 49 | (.catch 50 | (.then (js/Promise.resolve 42) 51 | #(js/console.log %)) 52 | #(js/console.log %)) 53 | #(js/console.log "cleanup")) 54 | 55 | ; same as above 56 | (-> (js/Promise.resolve 42) 57 | (.then #(js/console.log %)) 58 | (.catch #(js/console.log %)) 59 | (.finally #(js/console.log "cleanup"))) 60 | ---- 61 | 62 | Promise-heavy code that uses `await` results in more complicated code structures that aren't very 63 | friendly. 64 | Take this example from https://github.com/GoogleChrome/puppeteer#usage[Puppeteer usage]: 65 | 66 | *JavaScript:* 67 | [source,javascript] 68 | ---- 69 | const puppeteer = require('puppeteer'); 70 | 71 | (async () => { 72 | const browser = await puppeteer.launch(); 73 | const page = await browser.newPage(); 74 | try { 75 | await page.goto('https://example.com'); 76 | await page.screenshot({path: 'example.png'}); 77 | } catch (err) { 78 | console.log(err); 79 | } 80 | 81 | await browser.close(); 82 | })(); 83 | ---- 84 | 85 | *ClojureScript:* 86 | [source,clojure] 87 | ---- 88 | (def puppeteer (js/require "puppeteer")) 89 | 90 | (-> (.launch puppeteer) 91 | (.then (fn [browser] 92 | (-> (.newPage browser) 93 | (.then (fn [page] 94 | (-> (.goto page "https://clojure.org") 95 | (.then #(.screenshot page #js{:path "screenshot.png"})) 96 | (.catch #(js/console.log %)) 97 | (.then #(.close browser))))))))) 98 | ---- 99 | 100 | To tame this sort of code we turn to `core.async`. 101 | 102 | 103 | [[using-promises-with-core-async]] 104 | == Using Promises with core.async 105 | 106 | ClojureScript offers excellent facilities for async programming in https://github.com/clojure/core.async[core.async]. 107 | One especially handy tool is the `>*. 14 | 15 | This page documents how to integrate ClojureScript with a typical JavaScript 16 | bundler such as http://webpack.js.org[Webpack]. You should have 17 | http://nodejs.org[Node.js] installed. This guide assumes you have read through the Quick 18 | Start. This guide borrows liberally from this 19 | https://scotch.io/tutorials/setup-a-react-environment-using-webpack-and-babel[excellent 20 | guide on Webpack 2]. 21 | 22 | While we happen to use Webpack here, these instructions are easily adapted 23 | to other bundlers like Metro for React Native. 24 | 25 | [[setting-up]] 26 | == Setting Up Your Project 27 | 28 | First create a project directory: 29 | 30 | [source,bash] 31 | ``` 32 | mkdir hello-bundler 33 | cd hello-bundler 34 | ``` 35 | 36 | Create a `deps.edn` file the following contents: 37 | 38 | [source,clojure] 39 | ``` 40 | {:deps {org.clojure/clojurescript {:mvn/version "1.10.741"}}} 41 | ``` 42 | 43 | Create an empty `package.json` file: 44 | 45 | [source,bash] 46 | ``` 47 | echo "{}" > package.json 48 | ``` 49 | 50 | Add webpack and its command line tools: 51 | [source,bash] 52 | ``` 53 | npm install --save-dev webpack webpack-cli 54 | ``` 55 | 56 | We're now ready to setup our JS dependencies. 57 | 58 | [[javascript-dependencies]] 59 | === JavaScript Dependencies 60 | 61 | Install react and react-dom: 62 | 63 | [source,bash] 64 | ``` 65 | npm install --save react react-dom 66 | ``` 67 | 68 | Now create `src/hello_bundler/core.cljs` with the following contents: 69 | 70 | [source,clojure] 71 | ``` 72 | (ns hello-bundler.core 73 | (:require [react])) 74 | 75 | (.log js/console react/Component) 76 | ``` 77 | 78 | Notice that we are requiring React as if it was a normal require and a normal 79 | namespace. 80 | 81 | In order for this to work we need to set a couple of compiler options. Create 82 | a `build.edn` file with the following: 83 | 84 | [source,clojure] 85 | ``` 86 | {:main hello-bundler.core 87 | :output-to "out/index.js" 88 | :output-dir "out" 89 | :target :bundle 90 | :bundle-cmd {:none ["npx" "webpack" "./out/index.js" "-o" "out" "--mode=development"] 91 | :default ["npx" "webpack" "./out/index.js" "-o" "out"]} 92 | :closure-defines {cljs.core/*global* "window"}} ;; needed for advanced 93 | ``` 94 | 95 | Our build will generate `out/index.js` which is exactly the entry file that 96 | Webpack is looking for. We'll write the bundler result back into the output 97 | directory. 98 | 99 | Note the new `:target :bundle` option. This ensures that the generated code 100 | is compatible with popular JavaScript bundlers that can handle Node.js style 101 | `require`. It also sets a bunch of other sensible defaults like externs 102 | inference, so that advanced compilation will just work. `:bundle-cmd` is just 103 | an arbitrary shell command to run after the ClojureScript build completes. 104 | In the case of watching bundlers like Metro you probably won't bother with 105 | `:bundle-cmd`. 106 | 107 | Let's see this in action, the following will build your project then start 108 | a REPL: 109 | 110 | [source,bash] 111 | ``` 112 | clj -M -m cljs.main -co build.edn -v -c -r 113 | ``` 114 | 115 | Your default browser will open http://localhost:9000. Open the Developer Console, 116 | you should see that `React.Component` got logged. 117 | 118 | At the REPL you can require `react` and interact with it: 119 | 120 | [source, bash] 121 | ``` 122 | user> (require 'react) 123 | ``` 124 | 125 | [[overriding-foreign-lib]] 126 | == Overriding a Foreign Library 127 | 128 | You may find that you want to use React from `node_modules` perhaps because 129 | the latest bundled version hasn't yet appeared on CLJSJS. Yet, you still want to 130 | use some ClojureScript React binding like Reagent. ClojureScript supports this 131 | out of the box. 132 | 133 | To demonstrate this, change your `deps.edn` to the following: 134 | 135 | [source,clojure] 136 | ``` 137 | {:deps {org.clojure/clojurescript {:mvn/version "1.10.741"} 138 | reagent {:mvn/version "0.10.0" :exclusions [cljsjs/react cljsjs/react-dom]}}} 139 | ``` 140 | 141 | Change your source file to the following: 142 | 143 | [source,clojure] 144 | ``` 145 | (ns hello-bundler.core 146 | (:require [goog.dom :as gdom] 147 | [reagent.dom :as dom])) 148 | 149 | (defn simple-component [] 150 | [:div 151 | [:p "I am a component!"] 152 | [:p.someclass 153 | "I have " [:strong "bold"] 154 | [:span {:style {:color "red"}} " and red "] "text."]]) 155 | 156 | (dom/render [simple-component] (gdom/getElement "app")) 157 | ``` 158 | 159 | Rebuild your project, run the REPL: 160 | 161 | [source,bash] 162 | ``` 163 | clj -M -m cljs.main -co build.edn -v -c -r 164 | ``` 165 | 166 | To verify that externs inference allows advanced compilation to work, 167 | let's make an advanced build. REPLs don't work under advanced compilation 168 | so you'll have to manually open http://localhost:9000: 169 | 170 | [source,bash] 171 | ``` 172 | clj -M -m cljs.main -co build.edn -O advanced -v -c -s 173 | ``` 174 | 175 | That's it! 176 | 177 | [[webworkers]] 178 | == Building Webworkers 179 | 180 | When building webworkers with `:target :bundle`, you use webpack (or your 181 | preferred bundler) to add the webworker bootstrap. 182 | 183 | So your build's `:target` will still be `:bundle` (not `:webworker`), but you 184 | will tell your bundler to build a webworker. For example, with webpack you add the 185 | `--target=webworker` argument to your `:bundle-cmd` entries. 186 | 187 | You also need to define `cljs.core/*global*` as `"self"` (as opposed to 188 | `"window"` in browser builds). 189 | 190 | An example `build-webworker.edn` might look like: 191 | 192 | [source,clojure] 193 | ``` 194 | {:main hello-bundler.webworker 195 | :output-to "out/worker/index.js" 196 | :output-dir "out/worker" 197 | :target :bundle 198 | :bundle-cmd {:none ["npx" "webpack" "out/worker/index.js" "-o" "out/worker/main.js" "--target=webworker" "--mode=development"] 199 | :default ["npx" "webpack" "out/worker/index.js" "-o" "out/worker/main.js" "--target=webworker"]} 200 | :closure-defines {cljs.core/*global* "self"}} ;; needed for advanced 201 | ``` 202 | -------------------------------------------------------------------------------- /content/news/2017-06-26-welcome.adoc: -------------------------------------------------------------------------------- 1 | = Welcome to ClojureScript News! 2 | Alex Miller 3 | 2017-06-26 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | Welcome to the new ClojureScript news area! We'll have posts available here about important releases, features, and news. 9 | 10 | -------------------------------------------------------------------------------- /content/news/2017-06-27-faster-compilation-runtime-and-spec-caching-fixes.adoc: -------------------------------------------------------------------------------- 1 | = Faster Compilation/Runtime and Spec Caching Fixes 2 | ClojureScript Team 3 | 2017-06-27 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | Several exciting performance enhancements are in the ClojureScript 1.9.660 9 | release. Some improvements speed up the compiler itself, others optimize the code 10 | generated by the compiler, and yet others fine tune data structures and common 11 | operations upon them. 12 | 13 | ## Compiler Performance 14 | 15 | With two small changes the compiler now compiles ClojureScript code much faster. 16 | Users have reported 20–40% faster compile times. 17 | 18 | Don't forget to try `:parallel-build`, which is not enabled by default. This can 19 | further cut your compile times in half. 20 | 21 | ## Code Performance 22 | 23 | * `:^const` Var values are now inlined 24 | * `sort`, `shuffle` is now 30-40% faster (thanks to `to-array` optimization) 25 | * `apply` is 200-400% faster 26 | * `defmulti` is now much faster in the case of a miss (200-1000%) 27 | * set and map equivalence is 100-200% faster 28 | * `reduce` on sets and maps is now ~100% faster 29 | 30 | ## Correctness 31 | 32 | Many correctness fixes have been made, several of them bringing ClojureScript 33 | more in line with Clojure behavior. Other important fixes were made with respect 34 | to compilation caching; notably code defining Specs now works properly when 35 | caching is enabled. 36 | 37 | > *NOTE*: that this release introduces a new warning for incorrect code which 38 | > employs variadic signatures in protocol method implementations. Such code will 39 | > continue to work with this release. Be sure to update any code or libraries that 40 | > make use of this construct so that protocol implementations match some existing 41 | > signature. 42 | 43 | ## New Features 44 | 45 | * A new `resolve` macro - like Clojure's but at compile-time 46 | * Modules support wildcard namespaces 47 | * New Closure language options `:es-2017`, `:es-next` 48 | * A new compiler option `:fn-invoke-direct` (a futher optimization extension to `:static-fns`) 49 | * You can use `js/Promise` and many more ES features and have Google Closure Compiler generate polyfills (`:rewrite-polyfills` compiler option) 50 | 51 | You should definitely give this release a try on your code to see how it 52 | performs! We hope you enjoy this release! 53 | 54 | For a complete list of updates in ClojureScript 1.9.660 see 55 | https://github.com/clojure/clojurescript/blob/master/changes.md#19660[Changes]. 56 | -------------------------------------------------------------------------------- /content/news/2017-07-07-sneak-preview.adoc: -------------------------------------------------------------------------------- 1 | = Sneak Preview 2 | ClojureScript Team 3 | 2017-07-07 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | ClojureScript's sixth birthday is fast approaching and will land on the second 9 | day of http://2017.euroclojure.org[EuroClojure]. To celebrate we will be 10 | publishing a series of posts over the next two weeks covering a variety of new 11 | and exciting features slated for the next release. 12 | 13 | Stay tuned! -------------------------------------------------------------------------------- /content/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules.adoc: -------------------------------------------------------------------------------- 1 | = ClojureScript is not an Island: Integrating Node Modules 2 | António Nuno Monteiro 3 | 2017-07-12 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | This is the second post in the 9 | https://clojurescript.org/news/2017-07-07-sneak-preview[Sneak Preview] series. 10 | 11 | ClojureScript has had first class JavaScript interop since its initial release 12 | in 2011. Similarly to Clojure, embracing the host has always been an explicit goal. 13 | While the above is true from a syntax standpoint, integrating with external 14 | JavaScript libraries historically came at the cost of some manual work footnote:[aside 15 | from the https://developers.google.com/closure/library/[Google Closure Library] 16 | which was deeply integrated since ClojureScript's initial release.] 17 | (https://clojurescript.org/reference/compiler-options#foreign-libs[manually assembled] 18 | bundles or packaging led by http://github.com/cljsjs/packages[community efforts]). 19 | 20 | === A step towards better interaction with external JavaScript 21 | 22 | The 2015 Google Summer of Code project for ClojureScript succeeded in making the 23 | interaction with foreign JavaScript modules easier. Relying on the 24 | https://developers.google.com/closure/compiler/[Google Closure Compiler]'s 25 | then new ability to understand most widely known JavaScript module formats and 26 | convert them to Closure compatible JavaScript footnote:[the subset of JavaScript 27 | that the Closure Compiler needs to perform optimizations such as dead code elimination 28 | (tree shaking), variable name rewriting, constant folding and inlining, among others.], 29 | https://github.com/MNeise[Maria Geller] successfully integrated those module features 30 | into ClojureScript, along with https://clojurescript.org/guides/javascript-modules#babel-transforms[custom preprocessing] 31 | steps that allow using features such as the popular JavaScript compilation technology 32 | http://babeljs.io/[Babel] from the comfort of your ClojureScript project 33 | footnote:[Maria also kept a regular blog whilst working on that project that you 34 | can read http://mneise.github.io/[here].]. 35 | 36 | Since then, the Closure Compiler team added module _resolution_ support in 2016, 37 | which among other things enables consuming modules directly from a `node_modules` 38 | installation instead of having to feed Closure handcrafted module paths for conversion. 39 | 40 | == Seamless interaction with NPM dependencies 41 | 42 | We have built on Maria's modules work to account for this new Closure feature, and 43 | the next release of ClojureScript represents yet another major milestone in making 44 | arbitrary JavaScript modules accessible to every ClojureScript project by including 45 | substantial improvements to the way that ClojureScript interoperates with the NPM 46 | ecosystem. 47 | 48 | https://anmonteiro.com/2017/03/requiring-node-js-modules-from-clojurescript-namespaces/[Requiring NPM modules from ClojureScript namespaces] 49 | has been possible since ClojureScript version 1.9.518. However, Node.js supports 50 | multiple patterns for requiring CommonJS modules, and a common painpoint was people 51 | looking to require modules of the form `"react-dom/server"` from ClojureScript, which 52 | would not be a valid symbol for the `:require` spec. 53 | 54 | In this release, we added support for string-based requires in the namespace form 55 | to solve the above problem. You can now require these types of modules from the 56 | comfort of your `ns` declaration. 57 | 58 | Gluing it all together is the `:npm-deps` compiler flag. In it, we tell the compiler 59 | which dependencies it should be aware of. ClojureScript will take care of installing 60 | those dependencies and running them through the Closure Compiler conversion pipeline, 61 | including optimizations which we describe in more detail below. 62 | 63 | === A practical example 64 | 65 | Given a `build.clj` file like the following: 66 | 67 | [source,clojure] 68 | ---- 69 | (require '[cljs.build.api :as b]) 70 | 71 | (b/build "src" 72 | {:output-dir "out" 73 | :output-to "out/main.js" 74 | :optimizations :none 75 | :main 'example.core 76 | :install-deps true 77 | :npm-deps {:react "15.6.1" 78 | :react-dom "15.6.1"}}) 79 | ---- 80 | 81 | Your simplest `src/example/core.cljs` file could look like the snippet below: 82 | 83 | [source,clojure] 84 | ---- 85 | (ns example.core 86 | (:require [react :refer [createElement]] 87 | ["react-dom/server" :as ReactDOMServer :refer [renderToString]])) 88 | 89 | (js/console.log (renderToString (createElement "div" nil "Hello World!"))) 90 | ---- 91 | 92 | Notice we don't have to declare `"react-dom/server"` anywhere. We can just require 93 | it. ClojureScript is now smart enough to find these CommonJS modules and process 94 | them into Google Closure Compiler compatible code. 95 | 96 | == This is a big deal 97 | 98 | The implications of consuming JavaScript modules with Google Closure are huge: the 99 | external libraries used in a ClojureScript project are no longer just prepended to 100 | the generated bundle, but can now be subjected to all of Closure Compiler's optimizations, 101 | including dead code elimination and, in projects that take advantage of 102 | https://clojurescript.org/news/2017-07-10-code-splitting[code splitting], cross 103 | module code motion. For example, in our tests React is appreciable smaller (~16%) 104 | under Closure's advanced compilation than it would be using existing popular JavaScript 105 | tooling footnote:[in fact, the Reagent team is already testing 106 | https://reagent-project.github.io/reagent-site-npm-deps-test/[a version of their website] 107 | to consume NPM modules. They also 108 | https://twitter.com/JuhoTeperi/status/885228578098601984[compared it] to the previous version]. 109 | Additionally, if you have a mixed codebase of ClojureScript and JavaScript, 110 | not only can you now seamlessly consume those JavaScript portions of your code 111 | (including e.g. JSX transformations!), but also share and bundle their vendor 112 | dependencies with the ones your ClojureScript part uses. 113 | 114 | === Works on Node.js too! 115 | 116 | It's worth noting that the module processing feature in ClojureScript is mostly 117 | intended to be used in projects that target the browser, where dependencies will 118 | normally be bundled together. But that doesn't mean projects targeting Node.js can't 119 | also take advantage of this feature. In fact, we made it so that you can also seamlessly 120 | require Node modules in a local `node_modules` installation from your namespace 121 | declaration when targeting Node.js. ClojureScript will know that you're requiring 122 | a Node module and produce a `require` declaration, integrating with Node.js's own 123 | facilities for loading JavaScript modules. 124 | 125 | == Parting thoughts 126 | 127 | ClojureScript is, after almost 6 years, a platform relied upon by a great number of 128 | developers worldwide, and we want to continue to deliver on full interoperability 129 | with the host. By making sure that we integrate with the vast JavaScript ecosystem 130 | out there, we think these new features arriving in the next version of ClojureScript 131 | are a stepping stone in assuring ClojureScript's sustainability long term. 132 | 133 | We hope you enjoy these new features as much as we do. Thanks for reading! 134 | -------------------------------------------------------------------------------- /content/news/2017-07-20-js-preprocessing-improvements.adoc: -------------------------------------------------------------------------------- 1 | = Simpler JavaScript Preprocessing 2 | Juho Teperi 3 | 2017-07-20 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | This is the fourth post in the link:/news/2017-07-07-sneak-preview[Sneak 9 | Preview] series. 10 | 11 | Closure compiler can process AMD, CommonJS and ES6 modules giving wide support 12 | for 13 | link:/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules[the 14 | Node ecosystem]. Even so, there are popular cases which Closure doesn't support 15 | directly, such as https://facebook.github.io/react/[React's] 16 | https://facebook.github.io/react/docs/introducing-jsx.html[JSX]. footnote:[There 17 | is https://github.com/mihaip/react-closure-compiler[third-party compiler pass] 18 | for Closure to support JSX] Maria Geller's Google Summer of Code work also 19 | addressed this based on a design outlined by David Nolen and a preprocessing 20 | hook has been present since 21 | https://github.com/clojure/clojurescript/blob/master/changes.md#1748[version 22 | 1.7.48]. However, the original design makes integration with other build tools 23 | challenging, and we've revised the approach to simplify such integrations. 24 | 25 | === Motivation 26 | 27 | JavaScript libraries using JSX or other syntax extensions are usually packaged 28 | with the already processed code so they can be used without further ceremony. 29 | Still, there are practical cases where one might want to include such code in 30 | the project directly. For example, when converting a project from JavaScript to 31 | ClojureScript it's far easier to reuse the existing code than attempt to rewrite 32 | everything in one go. Also, building sophisticated user interfaces is a team effort 33 | and tools like JSX can make that process far more welcoming by giving designers 34 | familiar tools. By allowing ClojureScript to reach JSX and other popular 35 | syntactical affordances, the ClojureScript development process can be 36 | more inclusive. 37 | 38 | == JavaScript transformation 39 | 40 | In the original design, preprocessing was enabled by providing `:preprocess` to 41 | a link:/reference/compiler-options#foreign-libs[foreign-lib map]. The value is a 42 | keyword dispatch for the `cljs.closure/js-transforms` multimethod. Users can 43 | implement a new multimethod case and, for example, use Java's built-in 44 | http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html[Nashorn 45 | JavaScript] engine to run a JavaScript compiler like https://babeljs.io/[Babel]. 46 | 47 | However, this approach creates complications for popular Clojure and 48 | ClojureScript build tools. The Clojure namespace that provides the preprocess 49 | multimethod must be loaded by the user before the ClojureScript compiler is run. 50 | While this may be feasible in an explicit build script, due to how both 51 | https://leiningen.org[Leiningen] and http://boot-clj.com[Boot] isolate the build 52 | to their own classpaths, this requirement simply isn't practical. 53 | 54 | There are a few ways to work around the original design: 55 | 56 | 1. Provide a new configuration option to enumerate the namespaces to `require` before 57 | running the compiler. 58 | 2. Create a relation between the multimethod dispatch keyword, and the namespace 59 | that provides the implementation. 60 | For example, if the keyword is namespaced, the namespace part of the keyword 61 | could be used to `require` that namespace on demand. 62 | 63 | Both of these solutions could be implemented at the build tools or in the 64 | ClojureScript compiler directly. The first option seems circuitous from an end 65 | user perspective, and while the second option highlights the fundamental problem, 66 | using keywords for this pattern seems unidiomatic. If we simply switch 67 | to symbols from keywords, we can align with existing precedents. 68 | 69 | === Preprocess symbol 70 | 71 | The next version of ClojureScript will support symbols as the `:preprocess` 72 | option value. Using a fully qualified symbol makes it obvious that the value 73 | refers to a function, and the namespace part of the symbol can be used to 74 | automatically load the namespace on the user's behalf. 75 | 76 | https://github.com/cljsjs/packages/blob/master/babel-standalone/README.md[cljsjs/babel-standalone] 77 | has been updated, and provides an easy way to use Babel with ClojureScript 78 | tooling following this new pattern. 79 | 80 | === Conclusion 81 | 82 | Users familiar with Clojure's philosophy know that we prioritize simplicity 83 | above most other qualities. But, simplicity is not always at odds with 84 | ease, and in fact, has long been been a language priority with respect 85 | to interoperability with the host. 86 | 87 | While Clojure has boasted excellent integration with Java for some time, for 88 | ClojureScript, the friction between Google Closure and mainstream JavaScript 89 | practice have made this promise more challenging to deliver. 90 | 91 | We believe we are closing the gap and that the vast ecosystem of JavaScript 92 | libraries can now finally be close at hand. -------------------------------------------------------------------------------- /content/news/2017-07-28-release-candidate.adoc: -------------------------------------------------------------------------------- 1 | = Release Candidate: 1.9.854 2 | ClojureScript Team 3 | 2017-07-28 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | Rather than delay further, we've decided to push out a release candidate 9 | containing all of the features we have announced so far and a number of features 10 | we simply haven't had time to cover in depth. To summarize the highlights: 11 | 12 | === Comprehensive Node Modules Support 13 | 14 | Whether you prefer https://www.npmjs.com[npm] or http://yarnpkg.com[yarn], 15 | ClojureScript can now consume dependencies from `node_modules` directly. There will 16 | be cases that don't work, but there will be many cases that do. We're 17 | particularly interested in feedback around this new capability. We expect to 18 | widen the scope of libraries the ClojureScript compiler can consume gradually over time. 19 | 20 | === JavaScript Module Preprocessing Enhancements 21 | 22 | The new release supports an enhanced approach to preprocessing JavaScript files 23 | which should remove friction with popular ClojureScript build tooling. 24 | 25 | === Checked Arrays 26 | 27 | ClojureScript can now check array operations. This feature encourages users 28 | to write idiomatic code while paving the way for further alignment with Clojure 29 | semantics. 30 | 31 | === Overhauled Code Splitting 32 | 33 | ClojureScript now ships with overhauled code-splitting functionality 34 | that eliminates the need for manual optimization. This feature is also 35 | coupled with a standard mechanism for loading code splits. 36 | 37 | === Global Exports for Foreign Libraries 38 | 39 | This feature has not yet received a post, but foreign libraries can now declare 40 | what they export. This means that foreign libraries can be treated as regular 41 | namespaces with all of the usual features (`:refer`, `:rename`, etc.). This 42 | enhancement also provides a smoother transition path from 43 | https://cljsjs.github.io[CLJSJS] dependencies to https://www.npmjs.com[npm] 44 | dependencies. Finally, for users bundling their JavaScript dependencies with 45 | http://webpack.js.org[Webpack], this feature makes consuming these foreign builds 46 | considerably more idiomatic. 47 | 48 | === Fixes, Changes, Enhancements 49 | 50 | Thanks to the efforts of the ClojureScript community, this release contains a 51 | large number of fixes, changes, and enhancements. For a full list 52 | https://github.com/clojure/clojurescript/blob/master/changes.md#19854[look 53 | here]. -------------------------------------------------------------------------------- /content/news/2017-07-30-global-exports.adoc: -------------------------------------------------------------------------------- 1 | = Global Exports for Foreign Libraries 2 | David Nolen 3 | 2017-07-30 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | Integration with the https://www.npmjs.com[npm] ecosystem promises to 9 | greatly reduce the friction around Closure-unaware JavaScript dependencies. 10 | However, this work is very much in progress and in no way precludes improving 11 | existing solutions to the problem of "foreign" dependencies. 12 | 13 | ClojureScript's `:foreign-libs` option has long provided a way to include 14 | JavaScript libraries which cannot be expected to pass through Closure advanced 15 | compilation. Through community efforts like http://cljsjs.github.io[CLJSJS], 16 | ClojureScript developers can reach functionality not readily provided by 17 | ClojureScript or Closure Library with relative ease. 18 | 19 | However, the design of `:foreign-libs` has always had a glaring flaw - these 20 | libraries are assumed to be globally loaded. Any API exported by the foreign 21 | library had to be accessed through the global environment: 22 | 23 | [source,clojure] 24 | ---- 25 | (ns foo 26 | (:require [cljsjs.react])) 27 | 28 | (def react js/React) 29 | ---- 30 | 31 | Thus foreign libraries supported none of the usual `:require` affordances like 32 | `:as`, `:refer`, `:rename`, etc. 33 | 34 | While this may seem like a minor point, over the years users have reached 35 | further and further into the JavaScript ecosystem for functionality not provided 36 | elsewhere. For many projects this meant using tools like 37 | https://webpack.github.io[Webpack] to package up all such dependencies into a 38 | single foreign library. While expedient, this approach leads to an unidiomatic 39 | style, and furthermore creates an obstacle should users try to migrate these 40 | dependencies to direct consumption from `node_modules` down the road. 41 | 42 | In the next release we are introducing a simple new enhancement to 43 | the `:foreign-libs` compiler option - `:global-exports`. A foreign library 44 | entry can now declare which namespace maps to which globally exported name: 45 | 46 | [source,clojure] 47 | ---- 48 | :foreign-libs [{:provides ["cljsjs.react"] 49 | :global-exports '{cljsjs.react React}} 50 | {:provides ["cljsjs.react.dom"] 51 | :global-exports '{cljsjs.react.dom ReactDOM}}] 52 | ---- 53 | 54 | With this simple change `cljsjs.react` can now be treated as a regular 55 | namespace: 56 | 57 | [source,clojure] 58 | ---- 59 | (ns foo 60 | (:require [cljsjs.react :as react :refer [createElement])) 61 | ---- 62 | 63 | Note that as `:global-exports` is a map of namespaces to global exports, users 64 | leveraging Webpack to make a single foreign library can easily map all the bundled 65 | libraries for idiomatic usage. 66 | 67 | This also provides a gradual migration path to `node_modules` if so desired. For 68 | example, a user could create a `cljsjs.react` artifact with a declared 69 | `:npm-deps` on React. Since foreign library usage is now unified with normal 70 | namespace usage, you can switch to `node_modules` dependencies with no actual 71 | changes in your source code, just changes to your dependencies in your 72 | dependency management tool of choice (Maven, Lein, Boot). 73 | 74 | We believe this feature addresses a long outstanding pain point and provides a 75 | smooth migration path to `node_modules` based dependencies. Please give it a try 76 | with ClojureScript 1.9.854 or later. 77 | -------------------------------------------------------------------------------- /content/news/2017-08-16-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.9.908 Release 2 | ClojureScript Team 3 | 2017-08-16 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | This release contains many bug fixes and addresses feedback from the 1.9.854 9 | release candidate. 10 | 11 | ## Simpler Module Loading 12 | 13 | Besides several important fixes, a small bit of automatic configuration from the 14 | new module loading feature has been removed. Any module that will be loaded via 15 | `cljs.loader` must require it and must invoke `cljs.loader/set-loaded!` manually 16 | as the final statement. All existing documentation and examples from previous 17 | posts have been updated. This simplification now means downstream libraries can 18 | easily build higher level composable facilities upon `cljs.loader`. 19 | 20 | ## Node Modules 21 | 22 | We're extremely excited to see users enthusiastically giving `:npm-deps` a try 23 | even at this early stage. Several limitations have been discovered and 24 | addressed, and we've even contributed patches back to Closure Compiler to push 25 | things forward. There's still a significant amount of work to do, so we encourage 26 | you to keep trying different libraries and telling us about your experiences. 27 | 28 | For a full list of enhancements, fixes, and changes 29 | https://github.com/clojure/clojurescript/blob/master/changes.md#19908[look here]. -------------------------------------------------------------------------------- /content/news/2017-08-16-release.adoc copy: -------------------------------------------------------------------------------- 1 | = 1.9.908 Release 2 | 3 | 2016-08-16 4 | :type: community 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | This release contains many bug fixes and ddresses a number of issues based on 11 | feedback from the 1.9.854 release candidate. 12 | 13 | ## Simpler Module Loading 14 | 15 | A small bit of automatic configuration magic from the new module loading feature 16 | has been removed. Any module that will be loaded via `cljs.loader` must require 17 | it and must invoke `cljs.loader/set-loaded!` as the final statement. All 18 | existing documentation and examples from previous posts have been updated. 19 | This simplification means downstream users can build higher level 20 | composable facilities upon `cljs.loader`. 21 | 22 | ## Node Modules 23 | 24 | We're extremely excited to see users enthusiastically giving `:npm-deps` a try 25 | even at this early stage. Several issues have been addressed and we've -------------------------------------------------------------------------------- /content/news/2017-10-03-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.9.946 Release 2 | ClojureScript Team 3 | 2017-10-03 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | This release contains many bug fixes and addresses feedback from the 1.9.908 9 | release. Important changes include parity with Clojure 1.9.0-beta1 and an 10 | updated Google Closure Compiler dependency. The later one in particular now 11 | means that ClojureScript has a dependency on JDK 8. 12 | 13 | For a full list of enhancements, fixes, and changes 14 | https://github.com/clojure/clojurescript/blob/master/changes.md#19946[look here]. -------------------------------------------------------------------------------- /content/news/2018-03-28-shared-aot-cache.adoc: -------------------------------------------------------------------------------- 1 | = Shared AOT Cache 2 | Mike Fikes 3 | 2018-03-28 4 | :jbake-type: post 5 | :icons: font 6 | 7 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 8 | 9 | When you compile ClojureScript code, several artifacts are produced, including JavaScript, analysis metadata, and source maps. These are cached locally, in an output subdirectory (typically “out” or “target”). 10 | 11 | Since these artifacts are expensive to produce, it is tempting to include them in shipping library JARs. But, the artifacts vary, depending on the compiler version used as well as the build-affecting compiler options in effect (such as `:target`, `:elide-asserts`, or `:static-fns`), so this approach is infeasible. 12 | 13 | A new feature in ClojureScript can effectively solve this problem: When enabled, compilation artifacts produced from JARs are placed in a shared cache. This means that you can compile, say, `core.async` 0.4.474 _once_. 14 | 15 | The shared cache can be reused across the different ClojureScript projects you might have on your computer. It can also be used as a source to populate your output directory if you perform a “clean” in a project and build it from scratch. This can drastically reduce the build time, as you are only compiling the source in your project proper. 16 | 17 | Since ClojureScript itself is typically a JAR dependency, the shared AOT cache mechanism is—in typical Lisp meta-circular fashion—applicable to ClojureScript _itself_, caching artifacts produced for `cljs.core` and other namespaces that ship with ClojureScript. 18 | 19 | This enables a new feature of `cljs.main`: For certain use cases, like simply using it to run a script, evaluate a form with `-e`, or just fire up a REPL, `cljs.main` will use a _temporary_ output directory instead of dirtying the filesystem by creating an “out” directory where you ran `cljs.main`. The ability to use an AOT `cljs.core` makes this use case nice and zippy. 20 | 21 | The AOT cache logic is smart enough to deal with different compiler versions, build-affecting options, and JAR names, and uses that information to store artifact variants separately in the cache. And, while the AOT cache feature is motiviated by the notion that code in shipping JARs is immutable, it recognizes that this does not hold in the case of snapshot JARs or locally deployed JAR revisions. In those cases, the change in a JAR's timestamp will invalidate the cache. 22 | 23 | [NOTE] 24 | ==== 25 | The AOT cache logic cannot handle the case where shipping JARs employ macros that consult the ambient environment in order to affect the code generated for the source shipped in those JARs. 26 | 27 | An example might be the use of macros to cause the compiled code to reflect configuration, as is the case if you use `:external-config` with Figwheel or Dirac. 28 | 29 | In those situations, it is recommended that libraries and tooling employ `goog.define` instead, perhaps with the help of https://clojurescript.org/reference/compiler-options#closure-defines[`:closure-defines`], as this makes JARs cache-friendly. 30 | ==== 31 | 32 | By default, this feature is disabled unless ClojureScript is being used via `cljs.main`. You can override the default by explicitly using the new https://clojurescript.org/reference/compiler-options#aot-cache[`:aot-cache`] compiler option. 33 | 34 | Since this strategy doesn't depend on AOT artifacts being included in shipping JARS, it should be amenable to https://clojure.org/news/2018/01/05/git-deps[Git Deps]. Perhaps that will come in a future release of ClojureScript. 35 | 36 | We encourage you to give this feature a try. Our hope is that this feature is one that you don't end up even thinking about, and that it just further helps get you to your day-to-day development! 37 | -------------------------------------------------------------------------------- /content/news/2018-06-15-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.312 Release 2 | ClojureScript Team 3 | 2018-06-15 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | ## Improved Externs Inference 9 | 10 | Externs inference has been significantly improved in this release. See https://clojurescript.org/guides/webpack[ClojureScript with Webpack] for details on what this improved support enables. 11 | 12 | ## Closure Upgrades 13 | 14 | Closure Compiler has been upgraded to v20180610. 15 | 16 | Additionally, changes have been made so that it is possible to upgrade to the latest Google Closure Library. (The revised code is simultaneously compatible with the latest Closure Library and the version that ClojureScript 1.10.238 depends on.) 17 | 18 | ## Optimized `node_modules` Indexing 19 | 20 | If you use `:npm-deps`, the indexing of `node_modules` should be much faster. (One test showed a 6-fold improvement in indexing speed.) 21 | 22 | ## Improvements in Testing 23 | 24 | Several improvements have been made to ensure that the compiler test suite passes on Windows. Additionally, Graal.js, the new JavaScript engine that ships with GraalVM is included in the test suite. 25 | 26 | For a complete list of updates in ClojureScript 1.10.312 see 27 | https://github.com/clojure/clojurescript/blob/master/changes.md#110312[Changes]. 28 | 29 | ## Contributors 30 | 31 | Thanks to all of the community members who contributed to ClojureScript 1.10.312: 32 | 33 | * Andre Rauh 34 | * Dieter Komendera 35 | * Erik Assum 36 | * Jannis Pohlmann 37 | * Juho Teperi 38 | * Mike Fikes 39 | * Petter Eriksson 40 | * Pieter du Toit 41 | * Roman Scherer 42 | -------------------------------------------------------------------------------- /content/news/2018-11-02-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.439 Release 2 | ClojureScript Team 3 | 2018-11-02 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | ## Noteworthy Changes 9 | 10 | Closure Compiler has been upgraded to v20180805. 11 | 12 | The https://clojurescript.org/reference/compiler-options#npm-deps[`:npm-deps`] 13 | compiler option now defaults to `false`. Previously, `:npm-deps` defaulted to 14 | `true`. 15 | 16 | ## Improved Compiler Performance 17 | 18 | The compiler is now much faster when compared with the 1.10.339 release for both regular builds 19 | and when `:parallel-build` is set to `true`. 20 | 21 | ## Warnings on Private Var Use 22 | 23 | ClojureScript will now warn on private var use. 24 | 25 | Let's say you have a function intended for private use in a namespace: 26 | 27 | [source,clojure] 28 | ---- 29 | (ns foo.core) 30 | 31 | (defn- some-impl [x] 32 | (inc x)) 33 | ---- 34 | 35 | and you inadvertently use it from some other namespace, as in 36 | 37 | [source,clojure] 38 | ---- 39 | (ns bar.core 40 | (:require [foo.core])) 41 | 42 | (foo.core/some-impl 3) 43 | ---- 44 | 45 | The compiler will now emit a helpful diagnostic: 46 | 47 | [source] 48 | ---- 49 | WARNING: var: foo.core/some-impl is not public 50 | ---- 51 | 52 | This is only a warning; the ClojureScript compiler continues to allow private var use, but now emits a new analysis warning, controllable via `:private-var-access`. 53 | 54 | If var indirection is used instead, no warning will be emitted: 55 | 56 | [source, clojure] 57 | ---- 58 | (#'foo.core/some-impl 3) 59 | ---- 60 | 61 | ## Function Return Type Inference 62 | 63 | ClojureScript now infers function return types, propagating this information 64 | to call sites. 65 | 66 | Consider these predicates: 67 | 68 | [source,clojure] 69 | ---- 70 | (defn finite? [x] 71 | (not (infinite? x))) 72 | 73 | (defn big? [x] 74 | (and (pos? x) 75 | (finite? x))) 76 | ---- 77 | 78 | Previously, code like the following 79 | 80 | [source,clojure] 81 | ---- 82 | (if (big? 11) 83 | "hi" 84 | "bye") 85 | ---- 86 | 87 | would emit defensive JavaScript that coerces the return value of `big?` 88 | to a Boolean by using `cljs.core.truth_`: 89 | 90 | [source,javascript] 91 | ---- 92 | (cljs.core.truth_(cljs.user.big_QMARK_.call(null,(11)))?"hi":"bye") 93 | ---- 94 | 95 | Now, the compiler instead infers that `finite?` always returns a Boolean 96 | value, and therefore so does `big?`, and emits more efficient code: 97 | 98 | [source,javascript] 99 | ---- 100 | ((cljs.user.big_QMARK_.call(null,(11)))?"hi":"bye") 101 | ---- 102 | 103 | With inference like this, it is no longer necessary to manually add a `^boolean` 104 | type hint to a predicate used in performance-critical code, so long as 105 | the return value can be infered from the predicate function body. 106 | 107 | In general, any inferred types will automatically flow from 108 | function bodies outward, such as an inferred numeric type in the following 109 | example: 110 | 111 | [source,clojure] 112 | ---- 113 | (defn foo [x] 114 | (+ x 3)) 115 | ---- 116 | 117 | If `foo` is used in a context where types are checked, as in 118 | 119 | [source,clojure] 120 | ---- 121 | (+ (foo 1) "a") 122 | ---- 123 | 124 | you will now see a warning that properly reflects the type: 125 | 126 | [source] 127 | ---- 128 | WARNING: cljs.core/+, all arguments must be numbers, got [number string] instead 129 | ---- 130 | 131 | Previously, without a type hint on `foo`, the compiler would produce a 132 | warning that indicates a type of `any` instead of `number`. 133 | 134 | ## Graal.JS REPL Environment 135 | 136 | ClojureScript now ships with a Graal.JS REPL environment. This is a new Java-based REPL 137 | environment which is similar to the existing Nashorn REPL environment, but instead uses 138 | the new https://github.com/graalvm/graaljs[Graal.JS] JavaScript engine that ships as part of GraalVM. 139 | 140 | The Graal.JS REPL environment automatically configures the Graal.JS engine to allow 141 | Polyglot calls to other languages that may be installed. 142 | 143 | If you have the GraalVM version of Java on your path, to use this new REPL environment 144 | with `cljs.main`, simply specify `--repl-env graaljs`: 145 | 146 | [source] 147 | ---- 148 | $ clj -M --main cljs.main --repl-env graaljs --repl 149 | ClojureScript 1.10.439 150 | cljs.user=> (.eval js/Polyglot "R" "sum(1:100)") 151 | 5050 152 | cljs.user=> (.eval js/Polyglot "ruby" "(1..100).reduce(:+)") 153 | 5050 154 | ---- 155 | 156 | In addition to Polyglot support, the Graal.JS engine is much faster than Nashorn, 157 | approaching the performance of the other leading JavaScript engines, especially when 158 | warmed up and the JVM has had an opportunity to optimize hotspots. 159 | 160 | Since GraalVM hasn't yet been released and things could still change, this new REPL environment 161 | should be considered beta. We encourage you to give it a try! 162 | 163 | ## Updates to Spec 164 | 165 | This release includes many updates to Spec, bringing changes and fixes that have been made to the 166 | Clojure implementation of Spec to ClojureScript. 167 | 168 | ## Updates to AST Representation 169 | 170 | The internal AST representation has been updated to match `tools.analyzer`. This will simplify things 171 | for tooling that works with the AST generated by ClojureScript. 172 | 173 | ## Change List 174 | 175 | For a complete list of updates in ClojureScript 1.10.439 see 176 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.439[Changes]. 177 | 178 | ## Contributors 179 | 180 | Thanks to all of the community members who contributed to ClojureScript 1.10.439: 181 | 182 | * Ambrose Bonnaire-Sergeant 183 | * Erik Assum 184 | * Eugene Kostenko 185 | * Henry Widd 186 | * Jordan Biserkov 187 | * Juho Teperi 188 | * Mike Fikes 189 | * Oliver Eidel 190 | * Ray McDermott 191 | * Thomas Spellman 192 | 193 | ## Grant Support 194 | 195 | Thanks to https://www.clojuriststogether.org[Clojurists Together] and its 196 | supporting members for funding a significant amount of work that went 197 | into this release! 198 | 199 | For details see 200 | 201 | - https://www.clojuriststogether.org/news/july-2018-monthly-update/[July 2018 Monthly Update] 202 | - https://www.clojuriststogether.org/news/june-2018-monthly-update/[June 2018 Monthly Update] 203 | - https://www.clojuriststogether.org/news/may-2018-monthly-update/[May 2018 Monthly Update] 204 | -------------------------------------------------------------------------------- /content/news/2019-01-31-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.516 Release 2 | ClojureScript Team 3 | 2019-01-31 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | ## Noteworthy Changes 9 | 10 | Spec instrumentation (`cljs.spec.test.alpha/instrument` and related functionality) 11 | no longer requires `test.check`. If you use `cljs.spec.test.alpha/check`, the data 12 | generation functionality of `test.check` is needed; in that case you need to require 13 | the `clojure.test.check` and `clojure.test.check.properties` namespaces. 14 | 15 | Keywords used in the `cljs.spec.test.alpha/check` API pertaining to Spec's use 16 | of `test.check` are now qualified with `clojure.spec.test.check`, thus aligning 17 | with Clojure. The previous way of qualifying with `clojure.test.check` is still 18 | supported. 19 | 20 | ## Clojure 1.10 Features 21 | 22 | ### Improved Exception Messages and Printing 23 | 24 | The https://www.clojure.org/reference/repl_and_main#_error_printing[improved exception infrastructure] added in Clojure 1.10 25 | has been ported to ClojureScript with this release. 26 | 27 | ### Protocols via Metadata 28 | 29 | The ability to add protocols via metadata (for protocols defined with 30 | the `:extend-via-metadata true` directive) has been ported to ClojureScript 31 | with this release. 32 | 33 | ### Datafy and Nav 34 | 35 | The `clojure.datafy` namespace has been ported to ClojureScript, 36 | along with associated protocols in the `clojure.core.protocols` namespace. 37 | 38 | ## clojure.edn Namespace 39 | 40 | A new `clojure.edn` namespace is added with this release which delegates to 41 | `cljs.reader` for functionality. This facilitates writing portable 42 | Clojure / ClojureScript source making use of `clojure.edn/read` and 43 | `clojure.edn/read-string`. 44 | 45 | ## Type Inference Improvements 46 | 47 | ### Predicate-Induced Type Inference 48 | 49 | The type inference algorithm will now consider core predicates when 50 | inferring the types of locals used in conditional expressions. 51 | 52 | For example, in 53 | 54 | [source,clojure] 55 | ---- 56 | (if (string? x) 57 | (inc x) 58 | 10) 59 | ---- 60 | 61 | because `x` satisfies `string?`, it will be inferred to be of string type 62 | in the then branch (and thus cause a warning to be emitted because `inc` 63 | is being applied to it). 64 | 65 | Because `cond` and `when` are macros built on top of `if`, predicate-induced 66 | inference also works as expected for expressions involving `cond` and `when`. 67 | 68 | In addition to core predicates, predicate-induced type inference also works 69 | for `instance?` checks. So, for example testing `(instance? Atom x)` will 70 | result in `x` being inferred of type `cljs.core/Atom`. 71 | 72 | ### Truthy-Induced Inference 73 | 74 | In situations where a value could potentially be `nil` (represented by the 75 | symbol `clj-nil` in type tags), if a simple symbol referring to such a value 76 | is used as the test in a conditional, the type inference algorithm will 77 | infer that the value cannot be `nil` in the then branch. 78 | 79 | This is perhaps best illustrated by way of example. Let's say you have 80 | the following function: 81 | 82 | [source,clojure] 83 | ---- 84 | (defn f [x] 85 | (when (even? x) 86 | (inc x))) 87 | ---- 88 | 89 | This function's return type is `#{number clj-nil}`, meaning that 90 | either a number or `nil` can be returned. 91 | 92 | The following function, which uses `f` and would previously be inferred as 93 | returning `#{number clj-nil}`, is now inferred as returning `number`: 94 | 95 | [source,clojure] 96 | ---- 97 | (defn g [y] 98 | (let [z (f y)] 99 | (if z 100 | z 101 | 17))) 102 | ---- 103 | 104 | In fact, owing to the way the `or` macro expands, the expression 105 | `(or (f 1) 17)` is now inferred as being simply `number`. 106 | 107 | ### Improved `loop` / `recur` Inference 108 | 109 | The type-inferrence algorithm will now consider `recur` parameter types 110 | when inferring `loop` local types. 111 | 112 | For example, in 113 | 114 | [source,clojure] 115 | ---- 116 | (loop [x "a"] 117 | (if (= "a" x) 118 | (recur 1) 119 | (+ 3 x))) 120 | ---- 121 | 122 | the local `x` would previously be inferred to be of string type (and 123 | this would cause a warning to be emitted for the expression adding it 124 | to `3`). Now, the compiler will infer `x` to be either string or numeric 125 | (and thus the warning will no longer appear). 126 | 127 | ### Multi-Arity and Variadic Function Return Type Inference 128 | 129 | ClojureScript 1.10.439 added https://clojurescript.org/news/news#_function_return_type_inference[function return type inference], but this capability 130 | only worked for single-arity functions. This release extends this capability 131 | to multi-arity and variadic functions. 132 | 133 | Furthermore, the inferred return type will properly vary if different 134 | arities return different types. For example, 135 | 136 | [source,clojure] 137 | ---- 138 | (defn foo 139 | ([x] 1) 140 | ([x y] "a")) 141 | ---- 142 | 143 | then the expression `(foo true)` will be inferred to be of numeric type 144 | while `(foo :a :b)` will be inferred to be of string type. 145 | 146 | ## Spec Improvements 147 | 148 | Several improvements in the Spec implementation are in this release, making it 149 | easier to spec functions in the standard core library, as well as improving 150 | instrumentation performance when a large number of functions in a codebase 151 | have specs. 152 | 153 | ## Improved Performance 154 | 155 | ### Chunked-Seq support for Ranges 156 | 157 | ClojureScript now supports chunked-seqs for ranges. An example where this 158 | capability improves performance is 159 | 160 | [source,clojure] 161 | ---- 162 | (reduce + (map inc (map inc (range (* 1024 1024))))) 163 | ---- 164 | 165 | which is evaluated 5 times faster in V8, 7 times in SpiderMonkey, and 2 times 166 | in JavaScriptCore. 167 | 168 | ### Improved `re-seq` Performance 169 | 170 | `re-seq` performance has been improved, with a speedup of 1.5 or more under major JavaScript engines. 171 | 172 | ### Optimized String Expression Concatenation 173 | 174 | Generally, arguments supplied to the `str` function are first coerced 175 | to strings before being concatenated. With this release, unnecessary 176 | coercion is eliminated for arguments that are inferred to be of string 177 | type, leading to more compact codegen as well as a speed boost. 178 | 179 | For example, in 180 | 181 | [source,clojure] 182 | ---- 183 | (defn foo [x y] 184 | (str (+ x y))) 185 | 186 | (str (name :foo/bar) "-" (foo 3 2)) 187 | ---- 188 | 189 | the last `str` expression is evaluated 3 times faster in V8 and 4 times 190 | faster in JavaSriptCore as a result of the improved codgen. 191 | 192 | ## Change List 193 | 194 | For a complete list of updates in ClojureScript 1.10.516 see 195 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.516[Changes]. 196 | 197 | ## Contributors 198 | 199 | Thanks to all of the community members who contributed to ClojureScript 1.10.516: 200 | 201 | * Anton Fonarev 202 | * Enzzo Cavallo 203 | * Erik Assum 204 | * Eugene Kostenko 205 | * Martin Kučera 206 | * Michiel Borkent 207 | * Oliver Caldwell 208 | * Sahil Kang 209 | * Thomas Heller 210 | * Thomas Mulvaney 211 | * Timothy Pratley 212 | * Will Acton 213 | -------------------------------------------------------------------------------- /content/news/2019-11-18-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.597 Release 2 | ClojureScript Team 3 | 2019-11-18 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | ## Noteworthy Changes 9 | 10 | * The behavior of `set/union` and `into` is now aligned with Clojure. 11 | * `subvec` argument checking is now aligned with Clojure. 12 | * `apply` `vector` on an array now properly clones the array. 13 | 14 | ## Google Closure Namespace Analysis 15 | 16 | The compiler now produces analysis metadata for Google Closure namespaces. 17 | This means that for these namespaces: 18 | 19 | * REPL facilities like `doc`, `dir`, `apropos`, _etc._, will now work. 20 | * Argument lists are available, thus enabling arity checking. 21 | * Return types are available, enhancing type inference. 22 | * Warnings on private var usage will be generated. 23 | 24 | To illustrate, let's `(require '[goog.crypt :as crypt])` and explore it 25 | at the REPL: 26 | 27 | Now, `(dir crypt)` will list the functions in that namespace: 28 | 29 | ---- 30 | byteArrayToHex 31 | byteArrayToString 32 | hexToByteArray 33 | ... 34 | ---- 35 | 36 | 37 | Docstrings are available; `(doc crypt/hexToByteArray)` produces: 38 | 39 | ---- 40 | ------------------------- 41 | goog.crypt/hexToByteArray 42 | ([hexString]) 43 | /** 44 | * Converts a hex string into an integer array. 45 | ... 46 | ---- 47 | 48 | Arity information is available. Passing an incorrect argument count to one 49 | of the functions, produces an arity warning. For example, 50 | `(crypt/hexToByteArray "abc" 123)` generates: 51 | 52 | ---- 53 | WARNING: Wrong number of args (2) passed to goog.crypt/hexToByteArray at line 1 54 | ---- 55 | 56 | ## Type Inference Improvements 57 | 58 | Several improvements to ClojureScript's type inference are in this release. 59 | 60 | ### Direct field access for keyword lookup on records 61 | 62 | This is easily explained by way of example: 63 | 64 | [source,clojure] 65 | ---- 66 | (defrecord Complex [re im]) 67 | 68 | (let [x (->Complex 1.1 2.7)] 69 | (:re x)) 70 | ---- 71 | 72 | The code generated for the last expression will be `x.re`. This can be 73 | anywhere between 66% and 450% faster. 74 | 75 | ### `count` specializations for string and array 76 | 77 | If you apply `count` to a value that is statically inferred to be 78 | either a string or an array, the JavaScript generated will 79 | involve direct access to the `length` field instead of a runtime 80 | call to `count`. 81 | 82 | For example `(count "abc")` will cause `"abc".length` to be emitted. 83 | Depending on context, this could be several orders of magnitude faster. 84 | 85 | ### `simple-*` / `qualified-*` predicate-induced inference 86 | 87 | If `simple-keyword?` or `qualified-keyword?` is satisfied for a 88 | local then that local is inferred to be a keyword. Similarly 89 | `simple-symbol?` or `qualified-symbol?` results in a local being 90 | as a symbol. 91 | 92 | This essentially broadens the existing predicate-induced inferrence 93 | for `keyword?` and `symbol?` to these additional core predicates. 94 | 95 | ### Thread predicate-induced inference through `and` 96 | 97 | This type inference improvement is perhaps best explained by way 98 | of an example. For the following code 99 | 100 | [source,clojure] 101 | ---- 102 | (and (string? x) (zero? (count x))) 103 | ---- 104 | 105 | the compiler will now know that, if the first clause in the `and` above 106 | is satisfied, then, in the second clause, `x` must be of type string. 107 | Combined with the `count` specialization mentioned above, this causes 108 | efficient JavaScript to be generated: 109 | 110 | [source,javascript] 111 | ---- 112 | typeof x === "string" && x.length === 0 113 | ---- 114 | 115 | ### Not inferring on `implements?` 116 | 117 | This is an internal, yet important, optimization for the standard library: 118 | When the `implements?` predicate is satisfied on a local, the compiler 119 | generates more efficient function dispatch code for expressions involving 120 | that local. 121 | 122 | ### Improperly widened cross-param `loop` / `recur` inference 123 | 124 | A corner-case involving `loop` / `recur` widening inference was fixed where 125 | incorrect inferrence can occur if a `loop`-bound local is used as a `recur` 126 | target. 127 | 128 | ### Dynamic Vars are now properly inferred as having type `any` 129 | 130 | An inference bug was fixed where dynamic Vars were incorrectly inferred 131 | as having the type of their initialization value. This was incorrect 132 | because dynamic Vars can be re-bound at runtime with values of types 133 | that differ from the initialization value type. 134 | 135 | ## Performance Improvements 136 | 137 | ### Optimize `assoc` on `IAssociative` values 138 | 139 | An optimization in the core `assoc` function makes it faster when `assoc` ing 140 | onto `IAssociative` values (the common case). 141 | 142 | For example, `assoc` ing a key-value onto a map can be 24% faster in V8 and 143 | 11% faster in JavaScript core, a great perf boost for this frequently 144 | used core function. 145 | 146 | ### Tag `coll` as `not-native` in `ci-reduce` 147 | 148 | This is an important internal optimization affecting the standard library 149 | which improves performance when reducing collections which are `IIndexed` 150 | and `ICounted`. 151 | 152 | ### Improve perf of `cljs.source-map.base64/encode` 153 | 154 | This improves the performance of a function heavily used in the generation 155 | of source maps, improving the performance by 17% in one of our measurements. 156 | 157 | ## Change List 158 | 159 | For a complete list of updates in ClojureScript 1.10.597 see 160 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.597[Changes]. 161 | 162 | ## Contributors 163 | 164 | Thanks to all of the community members who contributed to ClojureScript 1.10.597: 165 | 166 | * Dieter Komendera 167 | * Erik Assum 168 | * Herald 169 | * Martin Kavalar 170 | * Martin Kučera 171 | * Michiel Borkent 172 | * Roman Liutikov 173 | * Seçkin Kükrer 174 | * Thomas Mulvaney 175 | -------------------------------------------------------------------------------- /content/news/2020-04-24-bundle-target.adoc: -------------------------------------------------------------------------------- 1 | = Embracing JavaScript Tools 2 | ClojureScript Team 3 | 2020-04-24 10:35:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | ClojureScript 1.10.741 includes a new streamlined way to integrate with the 9 | existing JavaScript ecosystem - the bundle target. With this target, the output 10 | of the ClojureScript compiler can be immediately handed off to a JavaScript 11 | bundler like https://webpack.js.org[Webpack], 12 | https://facebook.github.io/metro/[Metro], or any other build tool that 13 | understands Node.js `require`. ClojureScript projects using this new target can 14 | freely integrate libraries from `node_modules` without handwritten externs or 15 | additional configuration, yet still fully leverage REPL-driven development and 16 | advanced compilation for the optimizable parts of their application. 17 | 18 | While the impact on ease of development for ClojureScript projects is 19 | obviously significant, we believe that the benefits for the ClojureScript 20 | ecosystem are even more exciting. You can now publish ClojureScript libraries 21 | that depend directly on the JavaScript ecosystem without additional ceremony 22 | and be confident that the whole community can benefit regardless of what 23 | other JavaScript and ClojureScript build tools they may prefer. 24 | 25 | If you want to cut to the chase and walk through a tutorial, head over to the 26 | <>. For some history and context, read on. 27 | 28 | Over the years we've implemented and shipped a variety of features to help 29 | integration with the JavaScript ecosystem, but the end result has, in truth, 30 | felt more like a patchwork of solutions than something cut from whole cloth. 31 | Some of this can be attributed to trying to work around JavaScript existing 32 | tooling rather than embracing it. ClojureScript has invested heavily in the 33 | advanced compilation capabilities of the decade-old 34 | https://developers.google.com/closure/compiler[Google Closure Compiler] 35 | project, and it seemed natural to pursue processing Node modules through it. 36 | 37 | But after nearly three years since we first shipped Node module processing via 38 | Closure, it's apparent that too few of the most popular libraries can be 39 | subjected to advanced optimizations. While we still believe there's promise 40 | here, the ClojureScript community will have to show the rest of the world the 41 | way by developing compelling JavaScript libraries that can be readily consumed 42 | by popular JavaScript tools, yet still be subjected to Closure's phenomenal tree 43 | shaking and code splitting when building with ClojureScript. The success of 44 | projects like https://rollupjs.org/guide/en/[Rollup.js] has shown that 45 | JavaScript developers are not adverse to adhering to a stricter style if it 46 | leads to significant benefits. In the meantime we need a simpler and, yes, 47 | easier way to get things done. 48 | 49 | In 50 | https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules[António 51 | Nuno Monteiro's original post] about Node module processing there's a fairly 52 | short paragraph about how under Node.js we actually generate Node.js `require` 53 | statements for libraries we know are coming from `node_modules`. This was a 54 | fantastic idea resulting in a very idiomatic experience when interacting 55 | with Node.js. Over the next couple of years it became apparent that using 56 | ClojureScript for Node.js was often simpler than web development. No longer, the 57 | bundle target approach embraces the fact that nearly all modern JavaScript 58 | dependency resolution is either Node.js `require` or ES6 import. 59 | 60 | Still, this only solves part of the problem. We need to apply advanced 61 | optimizations to ClojureScript generated JavaScript. Which leads us to something 62 | we call "externs inference". One of the tradeoffs with Closure's compilation model 63 | is that integrating libraries not intended for Closure consumption requires a 64 | manual and error-prone process of writing externs - files which prevent Closure 65 | from renaming properties and declarations from libraries it will not actually 66 | see. Because of an early decision by Rich Hickey to mark global variables in 67 | ClojureScript as such, and the fact that Clojure provides a simple but effective 68 | type propagation algorithm across a local scope which ClojureScript also 69 | implements, tracking the usage of "foreign" values is not as tricky as it would 70 | seem. 71 | 72 | Combining our approach for Node.js and externs inference leads us directly to 73 | the bundle target. Of course now it all probably seems pretty obvious - but 74 | juggling various design goals can easily obscure the simple answer. By taking 75 | two distinct things - on the one hand, ClojureScript, on the other, JavaScript 76 | tools - and actually allowing them to remain distinct - we can arrive at 77 | something more than the sum of the parts. At the same time, none of these choices 78 | precludes passing everything through Closure Compiler if more JavaScript 79 | libraries begin adopting a code style amenable to aggressive dead code 80 | elimination. 81 | 82 | This feature is the result of many discussions and inspiration from some great 83 | projects in the ClojureScript community - in particular https://github.com/drapanjanas/re-natal[re-natal] and 84 | https://shadow-cljs.org[shadow-cljs]. 85 | 86 | Happy hacking! 87 | -------------------------------------------------------------------------------- /content/news/2020-04-24-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.741 Release 2 | ClojureScript Team 3 | 2020-04-24 10:30:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully, 10 | there are two very significant changes. First, ClojureScript now ships with 11 | greatly enhanced support for integration with popular JavaScript bundling tools 12 | such as Webpack and Metro. Second, due to continuing changes to Google Closure 13 | Compiler and Library, we've decided to drop support for the Rhino and Nashorn 14 | REPLs to lower the maintenance burden around releases. 15 | 16 | ## Noteworthy Changes 17 | 18 | * Closure Compiler has been updated to `v20200112` 19 | * Closure Library has been updated to `0.0-20191016-6ae1f72f` 20 | * Rhino, Nashorn, and GraalJS REPLs have been removed 21 | 22 | The latest Closure Compiler & Library releases included a number of breaking 23 | changes which significantly increased the maintenance burden for this release. 24 | Given Closure Compiler & Library's recent pace of change, we've decided to focus 25 | our energies on the essential browser and Node.js REPLs. We've also begun 26 | enrichening the CLI & REPL APIs to ease third party efforts to target these 27 | JavaScript environments. 28 | 29 | ## New Core Features 30 | 31 | ## JavaScript Bundler Support 32 | 33 | * `:target :bundle` 34 | * `:bundle-cmd` 35 | * `:target-fn` 36 | * A new `--install-deps` CLI option 37 | 38 | We're happy to announce a significant new feature - the `:bundle` target. This 39 | target generates output that can be fed directly into popular JavaScript 40 | bundlers such as Webpack and Metro (for React Native). Not only does this 41 | greatly ease usage of Node modules, library creators can now distribute 42 | ClojureScript artifacts that depend on Node modules and be confident that users 43 | can consume these artifacts regardless of which build tool they may prefer. 44 | 45 | There's much more to say about the `:bundle` target, and we'll be releasing a 46 | separate post and guide soon. 47 | 48 | ### Iterator Support 49 | 50 | It is now possible to call `seq` on any object implementing JavaScript's 51 | Iterator protocol. A new core predicate, `cljs.core/js-iterable?` 52 | is introduced with this feature. 53 | 54 | For example, `(js-iterable? (js/Set.))` is `true` and 55 | 56 | [source,clojure] 57 | ---- 58 | (-> (doto (js/Set.) (.add 1) (.add 2)) 59 | seq) 60 | ---- 61 | 62 | can now produce `(1 2)`. 63 | 64 | ### Symbol Support 65 | 66 | A new core predicate `cljs.core/js-symbol?` has been added 67 | and printing has been revised to allow printing of symbols: 68 | 69 | ---- 70 | cljs.user=> (js/Symbol "abc") 71 | #object[Symbol(abc)] 72 | ---- 73 | 74 | ## Warning Improvements 75 | 76 | Single arity arithmetic operations will now warn on bad arguments: 77 | 78 | ---- 79 | cljs.user=> (+ "foo") 80 | WARNING: cljs.core/+, all arguments must be numbers, got [string] instead at line 1 81 | ---- 82 | 83 | ## Performance Improvements 84 | 85 | * `re-pattern`, `re-matches`, and `re-find` are now faster 86 | * Code gen better facilitates protocol static dispatch inlining 87 | * Fast initial prompt for browser REPL 88 | * Output size minimized for trivial "Hello World" programs 89 | 90 | ## Change List 91 | 92 | For a complete list of updates in ClojureScript 1.10.741 see 93 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.741[Changes]. 94 | 95 | ## Contributors 96 | 97 | Thanks to all of the community members who contributed to ClojureScript 1.10.741: 98 | 99 | * Camilo Polymeris 100 | * Colin Kahn 101 | * Dieter Komendera 102 | * Dominic Monroe 103 | * Roman Liutikov 104 | -------------------------------------------------------------------------------- /content/news/2021-04-06-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.844 Release 2 | ClojureScript Team 3 | 2021-04-06 10:30:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | ## Noteworthy & Breaking Changes 12 | 13 | * Closure Compiler has been updated to `v20210302` 14 | * Closure Library has been updated to `0.0-20201211-3e6c510d` 15 | 16 | Note that the latest Closure Library release includes breaking changes that may 17 | impact your code: 18 | 19 | * `goog.debug.Logger.Level` has been renamed to `goog.Logger.Level` and the 20 | `goog.log.Level/getLogger` function now takes an additional argument. 21 | * The following JavaScript type checking predicates have been removed: 22 | `goog/isString`, `goog/isArray`, `goog/isFunction`, `goog/isNumber`, and 23 | `goog/isBoolean`. 24 | * Closure namespace loading logic has been revised, necessitating updates to 25 | some REPLs. 26 | 27 | ## New Core Features 28 | 29 | ### Library Property Namespaces 30 | 31 | When consuming a JavaScript library which is exposed as a JavaScript 32 | object, you can now specify a property of this object to be used as a 33 | first-class namespace in ClojureScript. To do this, you use the `$` delimiter. 34 | 35 | For example, the `SubLib` property of a library object provided by `npm-lib` 36 | can be treated as a namespace like so: 37 | 38 | [source,clojure] 39 | ---- 40 | (ns foo 41 | (:require [npm-lib$SubLib :as sub-lib :refer [...]])) 42 | ---- 43 | 44 | If needed, you can also employ string-based requires: 45 | 46 | [source,clojure] 47 | ---- 48 | (ns foo 49 | (:require ["@npm/lib$SubLib" :as sub-lib :refer [...]])) 50 | ---- 51 | 52 | This feature can also be used to access `default` exports: 53 | 54 | [source,clojure] 55 | ---- 56 | (ns foo 57 | (:require [npm-lib$default :as npm-lib :refer [...]])) 58 | ---- 59 | 60 | The `$` delimiter is only needed to access the top-level object property; 61 | any nested properties are accessed via `.` as in the following example: 62 | 63 | [source,clojure] 64 | ---- 65 | (ns foo 66 | (:require [react-native$NativeModules.SomeBridge :as woz])) 67 | ---- 68 | 69 | ## Notable Fixes 70 | 71 | ### Accurate file name and line numbers in `cljs.test` 72 | 73 | Instead of inaccurately inferring file name and line numbers from the call stack 74 | in `do-report`, they are now captured during macro-expansion based on metadata. 75 | 76 | ### `sort` and `sort-by` retain meta 77 | 78 | This simple change makes `sort` and `sort-by` consistent with Clojure. For example, 79 | the following evaluates to `{:a true}`: 80 | 81 | [source,clojure] 82 | ---- 83 | (meta (sort (with-meta (range 10) {:a true}))) 84 | ---- 85 | 86 | ### Floating point issues with `range` 87 | 88 | Some floating point issues were addressed for `range`, making, for example 89 | `(range 0 (+ 1 (/ 9)) (/ 9))` have 10 elements and `(nth (range 0 1 0.1) 6)` 90 | properly evaluate to `0.6`. 91 | 92 | ### `#inst` parsing and printing, reflect proleptic Gregorian 93 | 94 | JavaScript employs a proleptic Gregorian date system and some bugs in ClojureScript's 95 | `#inst` support is now fixed for very old dates with respect to parsing and printing 96 | `#inst` values. 97 | 98 | ## Performance Improvements 99 | 100 | ### Reduce code generated by destructure macro for maps 101 | 102 | The code generated to implement map destructuring was optimized by introducing 103 | a shared helper to handle kw-args, reducing a portion of the Closure-optimized 104 | output from 35 bytes down to 5, a nice savings since map destructuring is 105 | frequently employed in code. 106 | 107 | ## Change List 108 | 109 | For a complete list of updates in ClojureScript 1.10.844 see 110 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.844[Changes]. 111 | 112 | ## Contributors 113 | 114 | Thanks to all of the community members who contributed to ClojureScript 1.10.844: 115 | 116 | * Arne Brasseur 117 | * Erik Assum 118 | * Hyunwoo Nam 119 | * Matthew Huebert 120 | * Thomas Heller 121 | -------------------------------------------------------------------------------- /content/news/2021-05-24-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.866 Release 2 | ClojureScript Team 3 | 2021-05-24 10:30:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | ## Noteworthy Changes 12 | 13 | * Closure Compiler has been updated to `v20210505` 14 | 15 | ## New Core Features 16 | 17 | ### `and` / `or` Optimization as Compiler Pass 18 | 19 | ClojureScript generates efficient JavaScript for `and` / `or`, 20 | employing `&&` / `||` when applied to Boolean values. Previously these 21 | optimizations were implemented directly by the `and` / `or` macros. With 22 | this release they are instead implemented during a compiler pass. 23 | 24 | A consequence of moving these optimizations to the code generation phase 25 | is that the resulting simplified `and` / `or` macros are compatibile with 26 | code walking libraries like `core.async`. 27 | 28 | ### Support Macros that Expand to `require` Statements 29 | 30 | > **NOTE:** this change been reverted in following releases as it was discovered 31 | > later (after many tests, including ClojureScript Canary) that there are many 32 | > scenarios which cannot work. It will not be reintroduced. 33 | 34 | This release allows macros that expand to `require` statements 35 | to be present in the code as is illustrated in the following example: 36 | 37 | [source,clojure] 38 | ---- 39 | (ns foo.bar 40 | (:require-macros [foo.baz :refer [macro-that-expands-to-require]])) 41 | (macro-that-expands-to-require) 42 | ---- 43 | 44 | ## Notable Fixes 45 | 46 | ### Support `IAssociative` `-contains-key?` Protocol Check in `contains?` 47 | 48 | The `IAssociative` protocol defines `-contains-key?`, which facilitates 49 | directly testing whether a key is in an associative collection. The core 50 | `contains?` function has been revised with this release to make such a 51 | call for collections that implement the `IAssociative` protocol. 52 | 53 | ### Higher-Order Checked Arrays 54 | 55 | With this release, the 56 | https://clojurescript.org/news/2017-07-14-checked-array-access[checked array access] 57 | feature is extended for higher-order uses of `aget` and `aset`. For example, 58 | 59 | [source,clojure] 60 | ---- 61 | (apply aget [(into-array [0]) 100]) 62 | ---- 63 | 64 | will now trigger a warning or error at runtime if this feature is enabled via 65 | https://clojurescript.org/reference/compiler-options#checked-arrays[compiler configuration]. 66 | 67 | ## Change List 68 | 69 | For a complete list of updates in ClojureScript 1.10.866 see 70 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.866[Changes]. 71 | 72 | ## Contributors 73 | 74 | Thanks to all of the community members who contributed to ClojureScript 1.10.866: 75 | 76 | * Arne Brasseur 77 | * Dieter Komendera 78 | * Dominic Monroe 79 | * Erik Assum 80 | * Wilker Lúcio 81 | -------------------------------------------------------------------------------- /content/news/2021-11-04-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.891 Release 2 | ClojureScript Team 3 | 2021-11-04 10:30:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | ## Noteworthy Changes 12 | 13 | * Closure Compiler has been updated to `v20210808` 14 | * Google Closure has been updated to `0.0-20211011-0726fdeb` 15 | 16 | ## Google Closure Library, goog.module & global access 17 | 18 | You should no longer assume that Google Closure Library namespaces can be 19 | reached globally because some dependency may have already loaded it. For 20 | proper usage of Google Closure Library namespaces, an explicit require is always 21 | necessary. 22 | 23 | Some ClojureScript libraries assume that because `cljs.core` loaded `goog.object`, 24 | it would be safe to refer to such definitions directly, i.e. `goog.object/get` without the necessary 25 | require. This pattern can be useful in the writing of macros so that users can 26 | elide a require. However, this is now an anti-pattern and will 27 | fail. 28 | 29 | Google has slowly been converting various namespaces to the `goog.module` 30 | format which does not export globally as `goog.provide` does. In order to future 31 | proof - ClojureScript now always loads `goog.module` in accordance with 32 | Closure's guidelines as Closure Library may decide to convert any namespace into 33 | a `goog.module` at any time and simply drop support for global definition for that 34 | namespace. 35 | 36 | To ease the transition for the most common cases, ClojureScript has a new 37 | compiler flag to restore the old behavior - `:global-goog-object&array`. 38 | 39 | Note the above guidance does not apply to ClojureScript libraries. To 40 | understand why, we briefly answer some related questions. 41 | 42 | ### Will ClojureScript use `goog.module`? 43 | 44 | No. Clojure style REPL driven development is best supported by the original 45 | Google Closure namespace conventions. By representing namespaces as nested 46 | JavaScript objects, we effectively get late bound environments that are 47 | semantically close to Clojure's vars which permit highly interactive development 48 | workflows. 49 | 50 | Like ES modules, the `goog.module` format is simply incompatible with REPL driven 51 | development. In both cases the module is effectively a function closure, precise 52 | redefinition is simply not a part of the design. The complexities and tradeoffs for interactive 53 | development are readily apparent when comparing typical JavaScript "hot-reloading" 54 | workflows and the development experience available to Clojure developers. 55 | 56 | ### What if Closure Compiler deprecates `goog.provide`? 57 | 58 | Fortunately Google Closure Compiler is very mature. Unlike currently popular JavaScript 59 | tools it does not need exports to understand what to tree-shake. Closure Compiler 60 | works on objects and their properties. Even if Closure Compiler removed `goog.provide`, 61 | we could simply provide our own analogous constructs and Closure Compiler would 62 | still be able to provide all the usual advanced optimizations. 63 | 64 | ## Change List 65 | 66 | For a complete list of updates in ClojureScript 1.10.891 see 67 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.891[Changes]. 68 | 69 | ## Contributors 70 | 71 | Thanks to all of the community members who contributed to ClojureScript 1.10.891: 72 | 73 | * Chance Russell 74 | -------------------------------------------------------------------------------- /content/news/2021-12-20-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.10.914 Release 2 | ClojureScript Team 3 | 2021-12-20 10:30:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | ## Noteworthy Changes 12 | 13 | * Handle Node.js package.json exports (fixes Firebase 9.X.X usage) 14 | * Fix regression around requiring `goog` 15 | * Fix regression around the Node.js REPL related to `goog.module` changes 16 | * Fix Windows platform issues 17 | 18 | ## Change List 19 | 20 | For a complete list of updates in ClojureScript 1.10.914 see 21 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.914[here] 22 | as well as https://github.com/clojure/clojurescript/blob/master/changes.md#1.10.896[here] 23 | -------------------------------------------------------------------------------- /content/news/2022-05-13-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.11.51 Release 2 | ClojureScript Team 3 | 2022-05-13 17:00:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | ## Clojure 1.11 parity 12 | 13 | This release includes support for `:as-alias`. It adds `update-vals` and 14 | `update-keys`. It introduces the `cljs.math` namespace, providing portability 15 | for code using `clojure.math`. `iteration`,`NaN?`, `parse-long`, `parse-double`, 16 | `parse-boolean`, and `parse-uuid` have also been added. 17 | 18 | This release also ports CLJ-2608, which adds support for trailing, conj-able 19 | element in map-destructuring support for seqs. 20 | 21 | ## Vendorization of tools.reader, data.json, and transit-clj 22 | 23 | ClojureScript is one of the largest libraries in the Clojure ecosystem. Having to 24 | compile some 20,000+ lines of Clojure code every time is a significant hit to 25 | REPL start times and other typical tasks. Thus ClojureScript is ahead-of-time (AOT) 26 | compiled. 27 | 28 | However, due to some subtle aspects of AOT this can lead to unresolveable 29 | dependency conflicts. Users have hit this issue with nearly all of the declared 30 | dependencies: transit-clj, data.json, and tools.reader. 31 | 32 | After conferring with the Clojure Team, we decided to vendorize all these 33 | dependencies. This way we can AOT everything and be confident that we won't 34 | create a conflict that can't easily be fixed via normal dependency management. 35 | ClojureScript no longer depends on transit-clj, only transit-java. The dependance 36 | on data.json has been removed. ClojureScript dependance on tools.reader is 37 | for a less common use case - bootstrapping the compiler to JavaScript. 38 | 39 | Some care was taken to ensure backwards compatibility, and we are particularly 40 | interested in any issues that people may encounter. 41 | 42 | ## Other Changes 43 | 44 | The minimum Clojure version for ClojureScript is now 1.10. Google Closure 45 | Compiler has been updated to the May release. 46 | 47 | For a complete list of updates in ClojureScript 1.11.51 see 48 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.11.51[here] 49 | 50 | ## Contributors 51 | 52 | Thanks to all of the community members who contributed to ClojureScript 1.11.51: 53 | 54 | * Tom Connors 55 | * Roland Thiolliere 56 | * David Frese 57 | * Paula Gearon 58 | * Matthew Huebert 59 | * Hyun-woo Nam 60 | * Timothy Pratley 61 | * Henry Widd 62 | -------------------------------------------------------------------------------- /content/news/2024-01-24-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.11.132 Release 2 | ClojureScript Team 3 | 2024-01-24 12:00:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | This is primarily a bugfix release. 12 | 13 | For a complete list of fixes, changes, and enhancements to ClojureScript see 14 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.11.132[here] 15 | 16 | ## Google Closure Compiler & Java 8 17 | 18 | This will probably be the last ClojureScript release to support Java 8 as Google 19 | Closure Compiler now requires Java 11. 20 | 21 | ## Google Closure Library Maintenance Mode & ClojureScript 22 | 23 | Google has https://groups.google.com/g/closure-library-discuss/c/FijyNE6_kt4[stopped developing Google Closure Library]. 24 | What does this mean for the future of ClojureScript? Not a whole lot. Google 25 | Closure Library is a project distinct from the Compiler that provides a large 26 | set of reusable battle-tested libraries that are Closure-compatible. As browsers 27 | and the JavaScript ecosystem have evolved, this project has become less 28 | important to Google. 29 | 30 | Google is not going to remove Google Closure Library (GCL), remove the API 31 | docs, or doing anything that would be detrimental to ClojureScript. Note that 32 | Google stopped providing regular releases many years ago - ClojureScript uses an 33 | artifact that we release ourselves. Even if Google did remove GCL from the 34 | Internet, we could still continue to provide the artifact and docs ourselves. 35 | 36 | The standard library, `cljs.core`, uses GCL in relatively simple ways, most of 37 | which could be replaced easily. This will likely happen over time and community 38 | contributions are welcome in this effort. 39 | 40 | The various built-in REPLs (Browser, Node) use a bit more GCL functionality and 41 | could also be evolved gradually over time. 42 | 43 | None of the above changes that we generate Google Closure Compiler compatible 44 | JavaScript and will continue to do so. Google itself embraced the wider 45 | JavaScript ecosystem, but they also transpile everything into Google Closure Compiler 46 | compatible JS (via https://github.com/angular/tsickle[tsickle]) before finally 47 | processing it with Google Closure Compiler. 48 | 49 | As always, we do not believe in creating meaningless churn for users. You can continue 50 | to rely on GCL in its current form for years. You can expect various base 51 | GCL namespaces (`goog.string`, `goog.object`, etc.) to be available as before. 52 | 53 | Looking towards the future, it is worth assessing Google's approach with tsickle 54 | to get the benefits of Closure advanced compilation without losing the ease 55 | provided by the JavaScript ecosystem. 56 | 57 | ## Contributors 58 | 59 | Thanks to all of the community members who contributed to ClojureScript 1.11.132: 60 | 61 | * Will Cohen 62 | * Michiel Borkent 63 | * John Newman 64 | * Enzzo Cavallo 65 | * Allen Rohner 66 | * Adam Kalisz 67 | * Erik Assum 68 | * Nikita Prokopov 69 | -------------------------------------------------------------------------------- /content/news/2025-05-16-release.adoc: -------------------------------------------------------------------------------- 1 | = 1.12.42 Release 2 | ClojureScript Team 3 | 2025-05-16 16:00:00 4 | :jbake-type: post 5 | 6 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 7 | 8 | We're happy to announce a new release of ClojureScript. If you're an existing 9 | user of ClojureScript please read over the following release notes carefully. 10 | 11 | This release features two significant dependency changes. First, Google Closure 12 | Compiler has been updated to `v20250402`. This change makes Java 21 a 13 | requirement for ClojureScript. The other significant change is that this release 14 | now depends on the Clojure fork of Google Closure Library. Please read on for 15 | more details about these changes. 16 | 17 | For a complete list of fixes, changes, and enhancements to 18 | ClojureScript see 19 | https://github.com/clojure/clojurescript/blob/master/changes.md#1.12.42[here] 20 | 21 | ## Google Closure Compiler & Java 21 22 | 23 | Last year we noted that updating Google Closure Compiler would mean losing Java 24 | 8 support. Google Closure now requires Java 21. From our perspective this change 25 | doesn't seem strictly necessary, but Google is a large organization and this 26 | change is likely to due to internal requirements which are hard to influence from 27 | the outside. The general enthusiasm in the Clojure community around adopting more 28 | recent Java releases hopefully softens the overall impact of this change. 29 | 30 | So far, the burden of staying current with Google Closure has been manageable. 31 | If for some reason that calculus changes, we could adopt the strategy we have taken 32 | with Google Closure Library. 33 | 34 | ## Clojure's Fork of Google Closure Library 35 | 36 | The incredible stability of Google Closure Library started declining around 37 | 2019. Google was both trying many things with respect to their internal 38 | JavaScript strategy as well as becoming less concerned about the impact on outside 39 | consumers. Finally, Google stopped contributing to Google Closure Library 40 | last August. 41 | 42 | We have forked Google Closure Library (GCL) and taken up maintenance. We backed out a 43 | few years of needless breaking changes and aligned the codebase with the latest 44 | Google Closure Compiler release. 45 | 46 | One of the biggest benefits of GCL is that it makes ClojureScript a complete 47 | solution for a variety of JavaScript contexts, not limited to the browser. 48 | Taking on additional dependencies always comes with a cost. One of 49 | ClojureScript's original value propositions was a rock solid set of readily 50 | available JavaScript tools as dependable as `clojure.core`. 51 | 52 | We are working on restoring that original stability. With this release, you'll 53 | find that quite a few old ClojureScript libraries work again today as well 54 | as they did *14 years* ago. 55 | 56 | ClojureScript is not and never was only just for rich web applications. Even in the 57 | post React-world, a large portion of the web is (sensibly) still using jQuery. If you need 58 | robust DOM manipulation, internationalization, date/time handling, color 59 | value manipulation, mathematics, programmatic animation, browser history management, 60 | accessibility support, graphics, and much more, all without committing to a framework 61 | and without bloating your final JavaScript artifact - ClojureScript is a one 62 | stop shop. 63 | 64 | Give it a try! -------------------------------------------------------------------------------- /content/news/news.adoc: -------------------------------------------------------------------------------- 1 | = News 2 | David Nolen 3 | 2017-06-26 4 | :jbake-type: news 5 | :toc: macro 6 | 7 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 8 | 9 | 10 | -------------------------------------------------------------------------------- /content/reference/advanced-compilation.adoc: -------------------------------------------------------------------------------- 1 | = Advanced Compilation 2 | David Nolen 3 | 2016-07-29 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | If you are targeting traditional JavaScript clients (web browsers) it's 13 | important to think about advanced compilation from the very beginning. 14 | Otherwise you will inevitably find yourself going through issues that 15 | could have been easily avoided with a little bit of up front 16 | preparation. In general do not wait to try an advanced build, you should 17 | always periodically generate a production build to catch issues sooner. 18 | 19 | [[avoid-foreign-libraries]] 20 | == Avoid Foreign Libraries 21 | 22 | It's best to simply avoid foreign libraries if a solution exists either 23 | in Google Closure Library or in an existing ClojureScript library. 24 | Foreign libraries must supply externs for advanced compilation to work 25 | consistently. 26 | 27 | Of course, in some cases foreign libraries cannot be avoided. 28 | 29 | [[using-foreign-libraries]] 30 | == Using Foreign Libraries 31 | 32 | If you must use a foreign library use a curated one like those provided 33 | by http://cljsjs.github.io[CLJSJS]. These come packaged with externs so 34 | that you do not have to supply them yourself. 35 | 36 | Occasionally you may find yourself needing a foreign library which has 37 | not been prepackaged. 38 | 39 | [[providing-externs]] 40 | == Providing externs 41 | 42 | When working with a foreign library which does not supply externs take 43 | the time to write an externs file for the API you intend to use. Externs 44 | files are surprisingly simple to provide. For example if the foreign 45 | library has some property `Foo.bar` that you wish to access your externs 46 | file should have the following entry: 47 | 48 | .... 49 | Foo.bar; 50 | .... 51 | 52 | If the foreign library has some method `Foo.baz` that you wish to invoke 53 | your externs file should have the following entry: 54 | 55 | .... 56 | Foo.baz = function() {}; 57 | .... 58 | 59 | Sometimes there will not be a top level API but rather some method 60 | naming convention, that is, an ad-hoc Interface / Protocol. In these 61 | cases define your externs using Object: 62 | 63 | .... 64 | Object.foo = function() {}; 65 | Object.bar = function() {}; 66 | .... 67 | 68 | Of course sometimes you will miss an extern entry and the the production 69 | file will produce a cryptic error. Thanks to a couple of Closure 70 | compiler options these issues are no longer difficult to debug. 71 | 72 | [[access-from-javascript]] 73 | == Access from JavaScript 74 | 75 | If you'd like to access ClojureScript code from JavaScript, then you 76 | will need to cope with the fact that advanced compilation will munge 77 | the JavaScript representation of 78 | your Var names. This can be easily addressed by adding `:export` metadata 79 | to Vars that should be consumable from JavaScript. 80 | 81 | For example, if you have a `square` function, you can annotate it with 82 | `^:export` as follows: 83 | 84 | [source,clojure] 85 | ``` 86 | (ns my-math.core) 87 | 88 | (defn ^:export square [x] 89 | (* x x)) 90 | ``` 91 | 92 | With this, you can call your `square` function from JavaScript as follows: 93 | 94 | [source,javascript] 95 | ``` 96 | my_math.core.square(3); 97 | ``` 98 | 99 | This works by including https://google.github.io/closure-library/api/goog.html#exportSymbol[`goog.exportSymbol`] 100 | calls in the emitted JavaScript wherever `:export` meta is associated 101 | with a Var. 102 | 103 | [NOTE] 104 | ==== 105 | For each exported Var, an additional un-renamed alias is established which points to the Closure-munged name. 106 | Munged names continue to be used internally within the optimized code. 107 | 108 | The `^:export` facility is for (and only for) providing external access to Vars via un-renamed aliases. 109 | If instead you'd like to debug optimized code which is using shortened names, consider `:pseudo-names` and `:pretty-print`, which are described in the following section. 110 | ==== 111 | 112 | You can individually export the Vars associated with protocol methods. In this example, `bar` and `quux` will be exported: 113 | 114 | [source,clojure] 115 | ``` 116 | (defprotocol IFoo 117 | (^:export bar [this]) 118 | (baz [this x]) 119 | (^:export quux [this x y])) 120 | ``` 121 | 122 | [[fixing-advanced-compilation-issues]] 123 | == Fixing Advanced Compilation Issues 124 | 125 | Change your production build to use two additional options 126 | `:pseudo-names true` and `:pretty-print true`. Now your error will show 127 | a name that corresponds to the name in the original source. Add an 128 | externs entry for this missed case. 129 | 130 | For more information about the specifics of `:foreign-libs` compiler 131 | option syntax consult <>. 132 | -------------------------------------------------------------------------------- /content/reference/bootstrapping.adoc: -------------------------------------------------------------------------------- 1 | = Bootstrapping the Compiler 2 | David Nolen 3 | 2016-07-29 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | See https://github.com/swannodette/cljs-bootstrap 13 | 14 | Current status: 15 | 16 | * ClojureScript can now compile both its analyzer & compiler w/o errors. 17 | Can eval non-trivial ClojureScript exprs from within the JS host. 18 | * Performance reading, analysis & compilation within bootstrapped 19 | ClojureScript has been optimized to be roughly within a factor of 2 of 20 | ClojureScript JVM (varying perf between engines). 21 | 22 | * Master is successfully being used in various contexts: 23 | ** https://github.com/swannodette/cljs-bootstrap[cljs-bootstrap] 24 | ** https://twitter.com/bus_kanaka/status/616026801412804608[Node.js REPL] 25 | ** http://clojurescript.net[Browser REPL] 26 | ** https://github.com/mfikes/replete[iOS REPL: Replete] 27 | ** https://github.com/tahmidsadik112/Replicator[Android REPL: Replicator] 28 | ** https://github.com/mfikes/planck[OS X REPL: Planck] 29 | ** https://jellea.github.io/QuilFiddle/[QuilFiddle] 30 | ** https://roman01la.github.io/threejs-cljs-playground/[Threejs 31 | playground] 32 | ** https://github.com/ScalaConsultants/replumb[Library for bootstrapped 33 | REPLs: Replumb] 34 | ** http://crepl.thegeez.net[crepl: collaborative repl] 35 | ** https://github.com/anmonteiro/lumo[Desktop REPL: Lumo] 36 | ** https://github.com/viebel/klipse[Embeddable clojurescript repl: KLIPSE] 37 | ** https://ctford.github.io/klangmeister[Musical live coding environment: Klangmeister] 38 | 39 | The following enumerates the remaining tasks: 40 | 41 | * Ensure perf is good. 42 | * Ensure defects are addressed. Many have `bootstrap` label: 43 | https://clojure.atlassian.net/issues/?jql=%20project%20%3D%20CLJS%20AND%20labels%20%3Dbootstrap[JIRA 44 | Query] 45 | * Determine if shared bootstrap REPL code will be included and 46 | implement. 47 | 48 | _* you can use the 49 | https://github.com/cljsinfo/api-refs/tree/catalog#-clojurescript-api-reference[CLJS 50 | API reference] to help identify imported macros and related Clojure 51 | types_ 52 | 53 | [[cljs-in-cljs-from-2012]] 54 | === cljs-in-cljs from 2012 55 | 56 | As a point of reference, https://github.com/kanaka/clojurescript is a 57 | previous project to bootstrap the ClojureScript compiler. It is fairly 58 | dated since it was forked from the main tree on Nov 16th, 2012, however, 59 | it was self-hosting and allowed for a fully browser-based REPL (original 60 | version of http://clojurescript.net/). A presentation of the project 61 | from Clojure West 2013 is here: 62 | http://www.infoq.com/presentations/cljs-in-cljs 63 | -------------------------------------------------------------------------------- /content/reference/documentation.adoc: -------------------------------------------------------------------------------- 1 | = Documentation 2 | David Nolen 3 | 2016-07-30 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | == API Documentation 11 | 12 | * http://cljs.info/cheatsheet/[ClojureScript Cheatsheet] 13 | * http://cljs.github.io/api/[ClojureScript Syntax and API Reference] 14 | * <> 15 | 16 | == Reference Documentation 17 | 18 | * <> 19 | * <> 20 | * <> 21 | * <> 22 | * <> 23 | * <> 24 | * <> 25 | * <> 26 | * <> 27 | * <> 28 | * <> 29 | * <> 30 | * <> 31 | -------------------------------------------------------------------------------- /content/reference/google-closure-library.adoc: -------------------------------------------------------------------------------- 1 | = Google Closure Library 2 | David Nolen 3 | 2016-07-29 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | ClojureScript projects always auto-include the 13 | https://developers.google.com/closure/library/[Google Closure Library], 14 | a massive library built and used by Google on many of their products 15 | (Gmail, Docs, etc). It has low-level utilities for DOM manipulation, 16 | server communication, animation, data structures, unit testing, 17 | rich-text editing, and UI widgets/controls. 18 | 19 | * http://google.github.io/closure-library/api/[Google Closure Library 20 | API Reference] 21 | 22 | [[try-the-wrapper-libraries-first]] 23 | === Try the wrapper libraries first! 24 | 25 | You may first want to consider the following ClojureScript libraries 26 | which wrap some functionality from Google Closure Library. Their source 27 | code also serves as good examples of how to use Closure directly. 28 | 29 | [cols="<*", options="header", role="table"] 30 | |======================================================================= 31 | |ClojureScript wrapper |Closure Libraries 32 | |https://github.com/andrewmcveigh/cljs-time[cljs-time] 33 | |https://google.github.io/closure-library/api/goog.date.html[goog.date] 34 | 35 | |https://github.com/r0man/cljs-http[cljs-http] 36 | |https://google.github.io/closure-library/api/goog.net.XhrIo.html[goog.net.XhrIo], 37 | https://google.github.io/closure-library/api/goog.Uri.html[goog.uri] 38 | 39 | |https://github.com/JulianBirch/cljs-ajax[cljs-ajax] 40 | |http://google.github.io/closure-library/api/goog.net.XhrIo.html[goog.net.XhrIo], 41 | http://google.github.io/closure-library/api/goog.Uri.html[goog.uri], 42 | http://google.github.io/closure-library/api/goog.json.html[goog.json] 43 | 44 | |https://funcool.github.io/cuerdas/latest/[cuerdas] 45 | |https://google.github.io/closure-library/api/goog.string.html[goog.string] 46 | 47 | |https://github.com/lambdaisland/glogi[glögi] 48 | |https://google.github.io/closure-library/api/goog.log.html[goog.log] 49 | |======================================================================= 50 | 51 | _* included in ClojureScript's core library_ 52 | 53 | [[using-google-closure-directly]] 54 | === Using Google Closure directly 55 | 56 | Some helpful blog posts: 57 | 58 | * http://clojurescriptmadeeasy.com/blog/do-not-forget-about-google-closure.html[ClojureScript 59 | Made Easy - Don't forget about Google Closure] 60 | * http://clojurescriptmadeeasy.com/blog/when-do-i-use-require-vs-import.html[ClojureScript 61 | Made Easy - When do I use :require vs :import?] 62 | 63 | To use Google Closure in your ClojureScript code, the rule is to use: 64 | 65 | * `:import` for Closure classes (which are also namespaces, like 66 | `goog.Uri`) and enums 67 | * `:require` for everything else 68 | 69 | [[import-a-class]] 70 | === Import a class 71 | 72 | This is only for when you would like to refer directly to a class which 73 | is _also_ a namespace, otherwise just use `:require` in your `ns` form 74 | or use the `require` REPL helper. 75 | 76 | [source,clojure] 77 | ---- 78 | (ns example.core 79 | (:import goog.Uri)) 80 | ---- 81 | 82 | [source,clojure] 83 | ---- 84 | ;; in REPL 85 | (import 'goog.Uri) 86 | (Uri. "http://example.com") 87 | ;;=> # 88 | ---- 89 | 90 | [[import-an-enum]] 91 | === Import an enum 92 | 93 | [source,clojure] 94 | ---- 95 | (ns example.core 96 | (:import [goog.events EventType])) 97 | ---- 98 | 99 | [source,clojure] 100 | ---- 101 | ;; in REPL 102 | (import '[goog.events EventType]) 103 | EventType.CLICK 104 | ;;=> "click" 105 | ---- 106 | 107 | [[requiring-a-function]] 108 | === Requiring a function 109 | 110 | [source,clojure] 111 | ---- 112 | (ns example.core 113 | (:require [goog.math :as math])) 114 | ---- 115 | 116 | [source,clojure] 117 | ---- 118 | ;; in REPL 119 | (require '[goog.math :as math]) 120 | (math/clamp -1 0 5) 121 | ;;=> 0 122 | ---- 123 | 124 | [WARNING] 125 | ==== 126 | Sometimes symbols are *not auto-included* when requiring their parent 127 | namespace. This happens when those symbols are in their own file and 128 | require specific inclusion 129 | ==== 130 | 131 | [source,clojure] 132 | ---- 133 | (ns example.core 134 | (:require 135 | [goog.string :as gstring] 136 | goog.string.format)) 137 | ---- 138 | 139 | [source,clojure] 140 | ---- 141 | ;; in REPL 142 | (require '[goog.string :as gstring]) 143 | (require 'goog.string.format) 144 | 145 | (goog.string.format "%05d" 123) 146 | ;;=> 00123 147 | 148 | ;; or use the alias 149 | (gstring/format "%05d" 123) 150 | ;;=> 00123 151 | ---- 152 | 153 | [[searching-for-examples]] 154 | === Searching for Examples 155 | 156 | You can look for `cljs` files on Github that use `goog.dom` with the 157 | following search: 158 | 159 | ---- 160 | Search GitHub: "goog.dom extension:cljs" 161 | ---- 162 | 163 | Or you can search Google Closure Library on Github for keywords 164 | pertaining to a function it might have: 165 | 166 | ---- 167 | Search Closure Library on Github: "hours minutes" 168 | ---- 169 | -------------------------------------------------------------------------------- /content/reference/javascript-api.adoc: -------------------------------------------------------------------------------- 1 | = JavaScript API 2 | Mike Fikes 3 | 2017-12-06 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | The implementation of ClojureScript collections define several JavaScript functions 13 | that can be called from ClojureScript using JavaScript interop or directly from 14 | JavaScript. This page describes those functions which are officially stable and 15 | publicly-consumable. 16 | 17 | [[indexOf]] 18 | === indexOf 19 | 20 | ==== Syntax 21 | 22 | [source,clojure] 23 | ---- 24 | (.indexOf coll search-value) 25 | (.indexOf coll search-value from-index) 26 | ---- 27 | 28 | ==== Parameters 29 | 30 | `coll` - a collection satisfying the `sequential?` predicate. 31 | 32 | `search-value` - the value to search for. 33 | 34 | `from-index` - an optional starting index. 35 | 36 | ==== Description 37 | 38 | Gets the index of a value in a sequential collection, or `-1` if 39 | not found. By default, search proceeds from the beginning, unless an 40 | optional starting index is supplied. 41 | 42 | ==== Examples 43 | 44 | [source,clojure] 45 | ---- 46 | (.indexOf [1 2 3 5 7] 5) ;; 3 47 | (.indexOf [1 2 3 5 7] 4) ;; -1 48 | (.indexOf [1 2 3 5 2] 2 3) ;; 4 49 | ---- 50 | 51 | [[lastIndexOf]] 52 | === lastIndexOf 53 | 54 | ==== Syntax 55 | 56 | [source,clojure] 57 | ---- 58 | (.lastIndexOf coll search-value) 59 | (.lastIndexOf coll search-value from-index) 60 | ---- 61 | 62 | ==== Parameters 63 | 64 | `coll` - a collection satisfying the `sequential?` predicate. 65 | 66 | `search-value` - the value to search for. 67 | 68 | `from-index` - an optional starting index. 69 | 70 | ==== Description 71 | 72 | Gets the last index of a value in a sequential collection, or `-1` if 73 | not found. By default, search proceeds from the end, unless an 74 | optional starting index is supplied. 75 | 76 | ==== Examples 77 | 78 | [source,clojure] 79 | ---- 80 | (.lastIndexOf [1 2 3 5 2 7] 2) ;; 4 81 | (.lastIndexOf [1 2 3 5 2 7] 4) ;; -1 82 | (.lastIndexOf [1 2 3 5 2 7] 2 3) ;; 1 83 | ---- 84 | -------------------------------------------------------------------------------- /content/reference/javascript-library-preprocessing.adoc: -------------------------------------------------------------------------------- 1 | = JavaScript Library Preprocessing 2 | Maria Geller 3 | 2016-10-03 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | ClojureScript allows you to add a custom transformation step for JavaScript libraries. This means that you are able to include JavaScript libraries in your project which are written in a dialect or make use of a JavaScript syntax extension. In order to effect the desired code transformation a `defmethod` which satisfies `cljs.closure/js-transforms` must be provided to the `:preprocess` option of the foreign library. For example, you can transform a JavaScript library using JSX into regular React function calls as follows: 11 | 12 | [source,clojure] 13 | ---- 14 | (require '[cljs.build.api :as b] 15 | '[clojure.java.io :as io]) 16 | (refer 'cljs.closure :only '[js-transforms]) 17 | (import 'javax.script.ScriptEngineManager) 18 | 19 | (defmethod js-transforms :jsx [ijs opts] 20 | (let [engine (doto (.getEngineByName (ScriptEngineManager.) "nashorn") 21 | (.eval (io/reader (io/file "babel.min.js"))) 22 | (.put "input" (:source ijs)))] 23 | (assoc ijs :source 24 | (.eval engine (str "Babel.transform(input, {presets: ['react']}).code"))))) 25 | 26 | (b/build "src" 27 | {:main 'my-project.core 28 | :output-to "out/my_project.js" 29 | :output-dir "out" 30 | :foreign-libs [{:file "libs/example.js" 31 | :provides ["my.example"] 32 | :preprocess :jsx}]}) 33 | ---- 34 | 35 | The example above uses Babel to transform the JavaScript code by loading a minified version of https://github.com/Daniel15/babel-standalone[babel-standalone] using Nashorn. The `js-transforms` method gets and returns an object which satisfies the `IJavaScript` protocol. The object can be a plain map or a record with keys like `:url`, `:provides`, `:requires` and `:source`. The second argument which is passed to `js-transforms` is a map with the compiler options. 36 | The JavaScript preprocessing happens before <>, however, both steps are independent of each other and can be used in disjunction. 37 | -------------------------------------------------------------------------------- /content/reference/javascript-module-support.adoc: -------------------------------------------------------------------------------- 1 | = JavaScript Module Support (Alpha) 2 | Maria Geller 3 | 2016-09-24 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | This page explains how to include a JavaScript module into a ClojureScript 13 | project. Please keep in mind that the functionalities described in this guide 14 | are still considered to be in alpha. 15 | 16 | [[motivation]] 17 | == Motivation 18 | 19 | In addition to code optimization and dependency management, the Google Closure 20 | compiler can also convert common JavaScript modules into Google Closure modules. 21 | Having a Google Closure module instead of a JavaScript module has the following 22 | advantages: 23 | 24 | * Google Closure modules are included into source code optimizations 25 | * no need to specify externs 26 | 27 | [[including-a-javascript-module]] 28 | == Including a JavaScript module 29 | 30 | Following, we will see how we can include the following simple CommonJS module 31 | into a ClojureScript project. 32 | 33 | [source,javascript] 34 | ---- 35 | // calculator.js 36 | var calculator = { 37 | add: function (a, b) { 38 | return a + b; 39 | }, 40 | subtract: function (a, b) { 41 | return a - b; 42 | } 43 | }; 44 | 45 | module.exports = calculator; 46 | ---- 47 | 48 | [[adding-a-javascript-module-to-your-project-configuration]] 49 | === Adding a JavaScript module to your project configuration 50 | 51 | If you want to include a JavaScript module into your project you need to add it 52 | as a foreign library and specify its module type using the `:module-type` 53 | compiler option. The module types that are currently supported are *CommonJS*, 54 | *AMD* and *ECMAScript 6*. Respectively, the values that can be specified for the 55 | `:module-type` compiler option are `:commonjs`, `:amd` and `:es6`. For example, 56 | the compiler options for the CommonJS module shown above are as follows: 57 | 58 | [source,clojure] 59 | ---- 60 | :foreign-libs [{:file "resources/libs/calculator.js" 61 | :provides ["calculator"] 62 | :module-type :commonjs}] 63 | ---- 64 | 65 | [[using-a-javascript-module-in-your-code]] 66 | === Using a JavaScript module in your code 67 | 68 | You can include a JavaScript module into a ClojureScript namespace by using the 69 | name that you've specified for the module with the `:provides` compiler option. 70 | For the CommonJS module shown above we've specified the name `calculator`. We 71 | can now use the module in our ClojureScript code in the same way as we would use 72 | modules from the <>. 73 | 74 | [source,clojure] 75 | ---- 76 | (ns my-project.core 77 | (:require [calculator :as calc])) 78 | 79 | (enable-console-print!) 80 | 81 | (println (calc/add 4 5)) 82 | ---- 83 | 84 | [[limitations]] 85 | == Limitations 86 | 87 | [[restrictions-imposed-by-the-google-closure-compiler]] 88 | === Restrictions imposed by the Google Closure compiler 89 | 90 | The Google Closure compiler expects its JavaScript input to conform to a few 91 | restrictions when using optimization levels `:simple` or `:advanced`. This means 92 | if you would like to use either of those optimization levels your JavaScript 93 | module has to conform to the restrictions imposed by the Google Closure 94 | compiler. See https://developers.google.com/closure/compiler/docs/limitations 95 | for more details about the restrictions. 96 | 97 | [[specifying-module-dependencies]] 98 | === Specifying module dependencies 99 | 100 | If your JavaScript module depends on other modules you need to add those modules 101 | to the project configuration as well. This can be infeasible for larger projects 102 | with many different modules. In this case you might want to try to bundle your 103 | project first and then include it as a single module. 104 | 105 | [[node.js-module]] 106 | === Node.js modules 107 | The https://nodejs.org/api/modules.html[Node.js module specification] varies 108 | slightly from the 109 | http://wiki.commonjs.org/wiki/Modules/1.1#Module_Identifiers[CommonJS 110 | specification] in that the module identifier that is passed to `require()` 111 | doesn't always need to be an absolute or relative path. This makes it difficult 112 | for the Google Closure compiler to resolve the dependencies of a node module 113 | since the compiler was implemented following the standard CommonJS specification. 114 | Therefore, it might not be possible for a node module to be converted to a 115 | Google Closure module. 116 | -------------------------------------------------------------------------------- /content/reference/packaging-foreign-deps.adoc: -------------------------------------------------------------------------------- 1 | = Packaging Foreign Dependencies 2 | David Nolen 3 | 2016-07-29 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | This page explains how to package non-Closure compatible JavaScript 11 | libraries for ClojureScript consumption. Before packaging a library make 12 | sure that it has not already been packaged by someone else. 13 | http://cljsjs.github.io[CLJSJS] is a promising community driven effort 14 | to provide a curated set of dependencies. To avoid duplication of effort 15 | and dependency conflicts it's recommended to contribute to a combined 16 | effort such as CLJSJS. 17 | 18 | When packaging a non-Closure compatible library for ClojureScript 19 | consumption make sure to include the development version of the library, 20 | the production version of the library, and an externs file. For example 21 | if you were packaging React for consumption the directory structure 22 | should probably look like the following: 23 | 24 | [source] 25 | ---- 26 | src/deps.cljs 27 | src/react/react.js 28 | src/react/react.min.js 29 | src/react/externs.js 30 | ---- 31 | 32 | Note that you must specify *deps.cljs* 33 | 34 | A *deps.cljs* file for React might look like the following: 35 | 36 | [source,clojure] 37 | ---- 38 | {:foreign-libs 39 | [{:file "react/react.js" 40 | :file-min "react/react.min.js" 41 | :provides ["com.facebook.React"]}] 42 | :externs ["react/externs.js"]} 43 | ---- 44 | 45 | Now users can simply add your JAR like any other dependency in their 46 | *pom.xml* or *project.clj* and require the `com.facebook.React` 47 | namespace in their ClojureScript source to import React. It's important 48 | to understand the namespace in this case is completely synthetic - 49 | foreign dependencies are always loaded globally. 50 | 51 | JARs may contain as many foreign libraries as you like just add more 52 | entries to the `:foreign-libs` vector. 53 | 54 | `:file-min` is completely optional but the above pattern is recommended 55 | for the best experience for library consumers. 56 | 57 | For a full example see 58 | https://github.com/swannodette/react-cljs[react-cljs]. 59 | 60 | If your foreign library has dependencies then you must enumerate them in 61 | a `:requires` vector. 62 | 63 | [source,clojure] 64 | ---- 65 | {:foreign-libs 66 | [{:file "jquery/jquery.js" 67 | :file-min "jquery/jquery.min.js" 68 | :provides ["org.jquery.jQuery"]} 69 | {:file "jquery/ui/core.js" 70 | :file-min "jquery/ui/core.min.js" 71 | :provides ["org.jquery.ui.Core"] 72 | :requires ["org.jquery.jQuery"]} 73 | {:file "jquery/ui/autocomplete.js" 74 | :file-min "jquery/ui/autocomplete.min.js" 75 | :provides ["org.jquery.ui.Autocomplete"] 76 | :requires ["org.jquery.ui.Core"]}] 77 | :externs ["jquery/jquery.js" "jquery/jquery.ui.js"]} 78 | ---- 79 | -------------------------------------------------------------------------------- /content/reference/repl-options.adoc: -------------------------------------------------------------------------------- 1 | = REPL Options 2 | David Nolen 3 | 2016-07-29 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | toc::[] 11 | 12 | ClojureScript REPLs can take nearly all the same options that can be 13 | supplied to `cljs.closure/build`, for details see <>. 14 | This page documents additional supported options. 15 | 16 | Note that options presented below under General Options should be passed 17 | as compiler options (via `-co` / `--compile-opts` if using `cljs.main`), while 18 | REPL-environment-specific options should be passed as REPL options 19 | (via `-ro` / `repl-opts` if using `cljs.main`). 20 | 21 | == General Options 22 | 23 | [[analyze-path]] 24 | === :analyze-path 25 | 26 | Sets a source path to analyze upon REPL initialization so that, if it 27 | connects to an already-running JavaScript environment, symbols for any 28 | previously loaded namespaces are available. May also be set to a vector 29 | of paths to analyze. 30 | 31 | [source,clojure] 32 | ---- 33 | :analyze-path "src" 34 | ---- 35 | 36 | [[def-emits-var]] 37 | === :def-emits-var 38 | 39 | Sets whether `def` (and derived) forms evaluated at the REPL return 40 | either a Var (if set to `true`) or the `def` init value (if `false`). 41 | Only affects forms evaluated at the REPL; compiled source behaves as if 42 | set to `false`. Default is `true`. 43 | 44 | [source,clojure] 45 | ---- 46 | :def-emits-var false 47 | ---- 48 | 49 | [[repl-requires]] 50 | === :repl-requires 51 | 52 | Specifies a set of lib specs (per the `require` REPL special) to be 53 | automatically loaded when launching a REPL. Defaults to specs that refer 54 | `doc` _etc._ along with `pp`. 55 | 56 | [source,clojure] 57 | ---- 58 | :repl-requires [[cljs.repl :refer-macros [source doc find-doc apropos dir pst]] 59 | [cljs.pprint :refer [pprint] :refer-macros [pp]]] 60 | ---- 61 | 62 | [[repl-verbose]] 63 | === :repl-verbose 64 | 65 | Enable verbose reporting for the REPL. Useful for debugging. Defaults to 66 | `false`. 67 | 68 | [source,clojure] 69 | ---- 70 | :repl-verbose true 71 | ---- 72 | 73 | This prints the compiled JavaScript before printing its evaluation: 74 | 75 | .... 76 | cljs.user=> (+ 1 2) 77 | ((1) + (2)) 78 | 3 79 | .... 80 | 81 | [[warn-on-undeclared]] 82 | === :warn-on-undeclared 83 | 84 | Overrides warnings related to the use of undeclared vars and non-existent 85 | namespaces at the REPL (specifically `:unprovided`, `:undeclared-var`, 86 | `:undeclared-ns`, and `:undeclared-ns-form`). Defaults to `true`. 87 | 88 | [source,clojure] 89 | ---- 90 | :warn-on-undeclared false 91 | ---- 92 | 93 | [[watch]] 94 | === :watch 95 | 96 | Watch a source directory for recompilation to avoid spinning up an 97 | additional JVM. 98 | 99 | [source,clojure] 100 | ---- 101 | :watch "src" 102 | ---- 103 | 104 | [[watch-fn]] 105 | === :watch-fn 106 | 107 | [source,clojure] 108 | ---- 109 | :watch-fn (fn [] (println "built!")) 110 | ---- 111 | 112 | A function of no arguments to run after a successful build. 113 | 114 | == Browser REPL Options 115 | 116 | These options are only applicable to the browser REPL that ships with ClojureScript. 117 | 118 | [[launch-browser]] 119 | === :launch-browser 120 | 121 | By default, starting the browser REPL launches the default browser configured with your operating system to connect back to it. You can disable this behavior by setting this option to `false`, and when doing so you will be prompted to connect with a message like 122 | 123 | [source,shell] 124 | ---- 125 | Waiting for browser to connect to http://localhost:9000 ... 126 | ---- 127 | 128 | [source,clojure] 129 | ---- 130 | :launch-browser false 131 | ---- 132 | 133 | [[working-dir]] 134 | === :working-dir 135 | 136 | The directory where the compiled REPL client JavaScript will 137 | be stored. Defaults to ".repl" with a ClojureScript version 138 | suffix, eg. ".repl-1.9-946". 139 | 140 | [[static-dir]] 141 | === :static-dir 142 | 143 | List of directories to search for static content. Defaults to 144 | `["." "out/"]`. 145 | 146 | [[src]] 147 | === :src 148 | The source directory containing user-defined cljs files. Used to 149 | support reflection. Defaults to `"src/"`. 150 | 151 | == Node REPL Options 152 | 153 | [[host]] 154 | === :host 155 | 156 | The host that the Node subprocess listens on for REPL traffic. 157 | 158 | [source,clojure] 159 | ---- 160 | :host "localhost" 161 | ---- 162 | 163 | [[port]] 164 | === :port 165 | 166 | The port that the Node subprocess listens on for REPL traffic. 167 | 168 | [source,clojure] 169 | ---- 170 | :port 49152 171 | ---- 172 | 173 | == Graal.JS REPL Options 174 | 175 | Executing `js --help:languages` will display a list of Graal.JS-specific options. 176 | Any REPL option with a string key starting with `"js."` will be passed through 177 | to the Graal.JS engine. Such entries should have string values. 178 | 179 | Here is an example enabling and using the ECMAScript Internationalization API: 180 | 181 | ---- 182 | $ clj -M -m cljs.main -re graaljs -ro '{"js.intl-402" "true"}' -r 183 | cljs.user=> (def gas-price (js/Intl.NumberFormat. "en-US" 184 | #js {:style "currency" 185 | :currency "USD" 186 | :minimumFractionDigits 3})) 187 | #'cljs.user/gas-price 188 | cljs.user=> (.format gas-price 5.259) 189 | "$5.259" 190 | ---- 191 | -------------------------------------------------------------------------------- /content/reference/source-maps.adoc: -------------------------------------------------------------------------------- 1 | = Source maps 2 | David Nolen 3 | 2016-07-29 4 | :type: reference 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | ClojureScript now supports HTML source maps so that you can debug 11 | ClojureScript directly in the browser, using the configuration option 12 | `:source-map`. 13 | 14 | `:source-map` can be either a boolean, or if optimizations are enabled, 15 | a path to a file for the map. 16 | 17 | Using the `bin/cljsc` script herein, you can run something like the 18 | following on the command line, adjusted for your project: 19 | 20 | [source,bash] 21 | ---- 22 | $ cljsc src '{:optimizations :whitespace :output-dir "out" :output-to "main.js" :source-map "main.js.map"}' 23 | ---- 24 | 25 | If you are building using leiningen, a similar section in `project.clj` 26 | would look something like: 27 | 28 | [source,clojure] 29 | ---- 30 | :cljsbuild { 31 | :builds [{:id "main" 32 | :source-paths ["src"] 33 | :compiler { 34 | :output-to "main.js" 35 | :output-dir "out" 36 | :optimizations :none 37 | :source-map true}}]}) 38 | ---- 39 | 40 | After compilation, you may then open an HTML file linking to the 41 | generated js file in Chrome. Make sure that source maps in Chrome are enabled via 42 | https://developer.chrome.com/devtools/docs/javascript-debugging#source-maps[the Chrome Developer Tools settings]. 43 | 44 | Source maps also work with `:optimizations` set to `:none`. In this case 45 | the `:source-map` value doesn't control file names. So long as the value 46 | is truth-y (cf. the leiningen example above), an individual source map 47 | file will be generated for every ClojureScript source file. 48 | 49 | It's important to note there are some source map option restrictions 50 | when using an `:optimizations` setting other than `:none`. In these 51 | cases `:output-to`, `:output-dir`, and `:source-map` must all share the 52 | exact same parent directory. The generated JavaScript file 53 | (`:output-to`) will contain a line at the end linking it to its source 54 | map like so: 55 | 56 | .... 57 | //# sourceMapping= 58 | .... 59 | 60 | The `sourceMapURL` is the `:source-map` path, relative to `:output-to`, 61 | since that is how the browser will then resolve it. For example, when 62 | given: 63 | 64 | [source,clojure] 65 | ---- 66 | {:output-to "resources/public/js/compiled/main.js" 67 | :output-dir "resources/public/js/compiled" 68 | :optimizations :simple 69 | :source-map "resources/public/js/compiled/main.js.map"} 70 | ---- 71 | 72 | The resulting `sourceMapURL` will be: `main.js.map`. 73 | 74 | [[web-server-integration]] 75 | === Web Server integration 76 | 77 | All source files will get copied into `:output-dir` so that they can be 78 | resolved, however this is not useful in the case where you have a web 79 | server. `:source-map-path` can be used to define an arbitrary path 80 | prefix. So instead of source map file references resolving to something 81 | like `resources/public/js/out` you can instead instead specify 82 | `:source-map-path "js/out"`. 83 | -------------------------------------------------------------------------------- /content/search.adoc: -------------------------------------------------------------------------------- 1 | = Search Results 2 | Rich Hickey 3 | 2015-01-01 4 | :type: search 5 | :toc: macro 6 | :icons: font 7 | 8 | ifdef::env-github,env-browser[:outfilesuffix: .adoc] 9 | 10 | -------------------------------------------------------------------------------- /content/tools/atom.adoc: -------------------------------------------------------------------------------- 1 | = Atom 2 | David Nolen 3 | 2016-08-02 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | [[packages]] 9 | == How to Install Atom Packages 10 | 11 | You can bring up your Atom settings by pressing `Command + ,` (command + comma) 12 | or `Control + ,` (control + comma) on Windows. From there, you can go to the 13 | "Install" tab and search for the name of the package you'd like to install. If 14 | you prefer using the command line, you can also use `apm` to install packages 15 | using: 16 | 17 | ---- 18 | $ apm install [package-name] 19 | ---- 20 | 21 | [[parinfer]] 22 | == Parinfer 23 | 24 | Unlike Java and Javascript, the convention in ClojureScript is to place closing 25 | delimiters on the same line instead of on a new line. To help manage this, 26 | Shaun LeBron's https://shaunlebron.github.io/parinfer/[Parinfer] can 27 | automatically balance your closing delimiters based on your code's indentation. 28 | Chris Oakman's Atom package for Parinfer can be found here: 29 | https://atom.io/packages/parinfer 30 | 31 | [[indentation]] 32 | == Improved Newline Auto-Indentation 33 | 34 | Atom, by default, does not auto-indent newlines correctly for Lisp dialects. You 35 | can solve this by installing Jon Spalding's 36 | https://atom.io/packages/lisp-paredit[lisp-paredit] Atom package. If 37 | you're already using Parinfer and only want to use the lisp-paredit package for 38 | newline indentation, you can change lisp-paredit's settings to: 39 | 40 | * Enabled: checked 41 | * Strict: unchecked 42 | * Keybindings Enable: unchecked 43 | 44 | ...and update your `keymap.cson` file with the following keybindings: 45 | 46 | ---- 47 | # Provides proper indentation when enter is pressed 48 | 'atom-text-editor[data-grammar~="clojure"]': 49 | 'enter': 'lisp-paredit:newline' 50 | 51 | # Override newline back to original when in Proto-REPL console 52 | # GitHub Issue: https://github.com/jonspalding/lisp-paredit/issues/26 53 | 'ink-console atom-text-editor[data-grammar~="clojure"]': 54 | 'enter': 'editor:newline' 55 | ---- 56 | 57 | NOTE: The `keymap.cson` file is found in the main menu under "Atom > Keymap...". 58 | 59 | [[linters]] 60 | == Joker Linter 61 | 62 | Roman Bataev's https://github.com/candid82/joker[Joker] linter can let you know 63 | when you've made an error in your code. Ryan De La Torre's Atom package for 64 | Joker can be found here: https://atom.io/packages/linter-joker 65 | 66 | To use this, you will also need to install Joker on your machine. You can 67 | download it https://github.com/candid82/joker/releases[here] or install it via 68 | Homebrew with: 69 | 70 | ---- 71 | brew install candid82/brew/joker 72 | ---- 73 | 74 | [[proto-repl]] 75 | == Proto REPL 76 | 77 | Jason Gilman's https://atom.io/packages/proto-repl[Proto REPL] allows you to 78 | evaluate ClojureScript code from your editor. 79 | 80 | === Setting Up Proto REPL with Figwheel 81 | 82 | If you're using Leiningen and Figwheel, the quickest way to connect Proto REPL 83 | to your application is to launch Figwheel from within Proto REPL. To do this, 84 | first merge `figwheel-sidecar`, `piggieback`, and `proto-repl` into your dev 85 | dependencies in your `project.clj`: 86 | 87 | [source,clojure] 88 | ---- 89 | :profiles {:dev {:dependencies [[figwheel-sidecar "0.5.9"] 90 | [com.cemerick/piggieback "0.2.1"] 91 | [proto-repl "0.3.1"]] 92 | ---- 93 | 94 | Next, add piggieback's nREPL middleware for ClojureScript in your `project.clj`: 95 | 96 | [source,clojure] 97 | ---- 98 | :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]} 99 | ---- 100 | 101 | Now open Proto REPL. You can do this by pressing `Command + Shift + P` (or 102 | `Control + Shift + P` on Windows) to bring up the Command Palette, then using 103 | the Command Palette to search for the `Proto REPL: Toggle` command. 104 | 105 | After starting Proto REPL, you should see the message, "Starting REPL with lein 106 | in [path to your project]" at the bottom of the REPL instructions. If all went 107 | well, you should be able to run the following command in Proto REPL to start 108 | Figwheel and start a ClojureScript REPL: 109 | 110 | [source,clojure] 111 | ---- 112 | (do (use 'figwheel-sidecar.repl-api) (start-figwheel!) (cljs-repl)) 113 | ---- 114 | 115 | Open your locally-hosted webpage in a browser, then try typing some test code 116 | into Proto REPL, such as `(js/alert "Hello from Proto REPL!")` to verify that 117 | everything is working. (The above command should cause an alert to appear in 118 | your browser.) 119 | 120 | === Saving Commands to Proto REPL 121 | 122 | If you don't want to type the command to start Figwheel every time, you can save 123 | a custom command to your Atom's `init.js`/`init.coffee` file: 124 | 125 | ---- 126 | atom.commands.add('atom-text-editor', 'Start Figwheel with CLJS REPL', function () { 127 | protoRepl.executeCode(` 128 | (when 129 | (try 130 | (require 'figwheel-sidecar.repl-api) 131 | (resolve 'figwheel-sidecar.repl-api/start-figwheel!) 132 | (catch Throwable _)) 133 | (eval '(do (figwheel-sidecar.repl-api/start-figwheel!) 134 | (figwheel-sidecar.repl-api/cljs-repl)))) 135 | `); 136 | }); 137 | ---- 138 | 139 | More documentation on extending Proto REPL can be found here: 140 | https://github.com/jasongilman/proto-repl/blob/master/extending_proto_repl.md 141 | -------------------------------------------------------------------------------- /content/tools/cursive.adoc: -------------------------------------------------------------------------------- 1 | = Cursive 2 | David Nolen 3 | 2016-08-02 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | https://cursive-ide.com[Cursive] is a plugin for IntelliJ that offers syntax highlighting, structural editing and navigation (paredit), code indexing / symbol lookup, refactoring, debugging, and static analysis / arity warnings. In addition, it includes an integrated REPL environment. 9 | -------------------------------------------------------------------------------- /content/tools/emacs-inf.adoc: -------------------------------------------------------------------------------- 1 | = Emacs and Inferior Clojure Interaction Mode 2 | David Nolen 3 | 2016-08-02 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | *This guide requires ClojureScript 1.10.238 or later and assumes 9 | familiarity with the <>*. 10 | 11 | Assuming you already have `clojure-mode`, run `M-x package-list-packages` and 12 | install `inf-clojure`. If you are using Emacs on OS X be sure to install 13 | `exec-path-from-shell` so that the Node.js REPL will work correctly. If you need 14 | `exec-path-from-shell` make sure to follow the 15 | https://github.com/purcell/exec-path-from-shell#usage[Usage] instructions. 16 | 17 | Edit your `.emacs` or `init.el` and add a function like the following if you are 18 | using the JAR in your current directory: 19 | 20 | [source,clojure] 21 | ---- 22 | (defun cljs-node-repl () 23 | (interactive) 24 | (inf-clojure "clj -M -m cljs.main -co build.edn -re node -r")) 25 | ---- 26 | 27 | Open your ClojureScript file and run `M-x cljs-node-repl`. You'll get a new 28 | buffer with the REPL. Switch back to your file and run `M-x 29 | inf-clojure-minor-mode`. `C-c C-l` will load the file. `C-c Meta-n` will switch 30 | your namespace. If you place your cursor at the end of a s-expression, `C-x C-e` 31 | will evaluate that expression. `C-c C-v` will show the docs. `C-c C-s` will show 32 | the source. `C-c ` will macroexpand. Refer to 33 | https://github.com/clojure-emacs/inf-clojure[inf-clojure] for more 34 | documentation. 35 | -------------------------------------------------------------------------------- /content/tools/leiningen.adoc: -------------------------------------------------------------------------------- 1 | = Leiningen 2 | Denis Baudinot 3 | 2021-07-11 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | https://leiningen.org/[Leiningen] is a build tool for Clojure and ClojureScript with an extensible plugin and template system. 9 | 10 | [[plugins]] 11 | == Plugins 12 | 13 | https://github.com/emezeske/lein-cljsbuild[lein-cljsbuild] provides ClojureScript compilation and file watching. For a more feature rich experience with browser hot reloading and CSS support head to https://github.com/bhauman/lein-figwheel[lein-figwheel]. 14 | -------------------------------------------------------------------------------- /content/tools/light-table.adoc: -------------------------------------------------------------------------------- 1 | = Light Table 2 | David Nolen 3 | 2016-08-02 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | http://www.lighttable.com[Light Table] is an extensible IDE that offers 9 | instant evaluation of your code, realtime feedback, and a ClojureScript 10 | plugin ecosystem. 11 | 12 | To get started, check out this concise 13 | http://docs.lighttable.com/#start[introduction] or the 14 | http://docs.lighttable.com/tutorials/full/[full tutorial]. 15 | 16 | Once you feel comfortable navigating Light Table's interface and using 17 | basic commands, it is advisable to install the official Paredit plugin. 18 | You can do so via the integrated plugin manager: open the command bar 19 | and look for `Plugins: Show plugin manager`. 20 | -------------------------------------------------------------------------------- /content/tools/shadow-cljs.adoc: -------------------------------------------------------------------------------- 1 | = shadow-cljs 2 | Denis Baudinot 3 | 2021-07-11 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | https://github.com/thheller/shadow-cljs[shadow-cljs] compiles, watches, hot reloads ClojureScript projects and provides targets and integration within the larger JavaScript ecosystem such as Nodejs, NPM and browser modules. It can be used as a standalone npm package to be run from the command line and a Clojure library to be integrated with other build tooling. 9 | 10 | From the shadow-cljs https://shadow-cljs.github.io/docs/UsersGuide.html[user guide]: 11 | 12 | [quote] 13 | shadow-cljs provides everything you need to compile your ClojureScript projects with a focus on simplicity and ease of use. The provided build targets abstract away most of the manual configuration so that you only have to configure the essentials for your build. Each target provides optimal defaults for each environment and get an optimized experience during development and in release builds. -------------------------------------------------------------------------------- /content/tools/sublime.adoc: -------------------------------------------------------------------------------- 1 | = Sublime Text 2 2 | David Nolen 3 | 2016-08-02 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | Install Sublime Text 2, install Sublime Text Package Control, use that to install the SublimeREPL package, 9 | and install the latest Leiningen. 10 | 11 | We recommend installing https://github.com/odyssomay/paredit[paredit], https://github.com/odyssomay/sublime-lispindent[lispindent], and http://github.com/wuub/SublimeREPL[SublimeREPL] which ships with support for ClojureScript. -------------------------------------------------------------------------------- /content/tools/testing.adoc: -------------------------------------------------------------------------------- 1 | = Testing 2 | David Nolen 3 | 2016-08-01 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | ClojureScript now ships with a port of `clojure.test` in the form of 9 | `cljs.test`. It attempts to preserve most of the functionality provided 10 | by `clojure.test` along with enhancements for asynchronous testing in a 11 | single threaded environment. 12 | 13 | Most of the functionality is provided via macros as `cljs.test` relies 14 | on compiler reflection and static vars to provide most of its 15 | functionality. 16 | 17 | For example your testing ns form will probably look something like the 18 | following: 19 | 20 | [source,clojure] 21 | ---- 22 | (ns my-project.tests 23 | (:require [cljs.test :refer-macros [deftest is testing run-tests]])) 24 | ---- 25 | 26 | [[writing-tests]] 27 | === Writing Tests 28 | 29 | You can write tests with `cljs.test/deftest` and `cljs.test/is` same as 30 | with `clojure.test`. 31 | 32 | For example here is a trivial test with one assertion: 33 | 34 | [source,clojure] 35 | ---- 36 | (deftest test-numbers 37 | (is (= 1 1))) 38 | ---- 39 | 40 | [[running-tests]] 41 | === Running Tests 42 | 43 | You can run tests by using the `cljs.test/run-tests` macro. This may be 44 | done in your REPL or at the end of your file. If you have many test 45 | namespaces it's idiomatic to create a test runner namespace which 46 | imports all of your test namespaces and then invokes `run-tests`. 47 | 48 | You may have to add `(enable-console-print!)` before calling `run-tests` 49 | 50 | [[fixtures]] 51 | === Fixtures 52 | 53 | You can declare fixtures with the `cljs.test/use-fixtures` macro. You 54 | can declare either `:once` fixtures or `:each` fixtures. `:once` 55 | fixtures are run only around all tests within a namespace. `:each` 56 | fixtures are run around each test. Unlike `clojure.test` fixtures are 57 | split into two parts `:before` and `:after`. This is so that fixtures 58 | will work correctly even when used asynchronously. 59 | 60 | [source,clojure] 61 | ---- 62 | (use-fixtures :once 63 | {:before (fn [] ...) 64 | :after (fn [] ...)}) 65 | ---- 66 | 67 | [[async-testing]] 68 | === Async Testing 69 | 70 | As client-side code tends to be highly asynchronous and JavaScript is 71 | single-threaded, it's important that `cljs.test` provide asynchronous 72 | testing support. You can use the `cljs.test/async` macro to create an 73 | asynchronous block. If you write an asynchronous test the last value you 74 | return _must_ be the async block. 75 | 76 | [source,clojure] 77 | ---- 78 | (deftest test-async 79 | (async done 80 | (http/get "http://foo.com/api.edn" 81 | (fn [res] 82 | (is (= res :awesome)) 83 | (done))))) 84 | ---- 85 | 86 | `done` is a function that you may invoke when you are ready to 87 | relinquish control and allow the next test to run. `done` can be called 88 | anything, but it probably makes sense to keep to the convention. All of 89 | your testing code must be in the async block. If you launch multiple 90 | asychronous processes in your async block you will need to coordinate 91 | them. This is a good reason to use `cljs.core.async`: 92 | 93 | [source,clojure] 94 | ---- 95 | (deftest test-async 96 | (let [url0 "http://foo.com/api.edn" 97 | url1 "http://bar.com/api.edn" 98 | res0 (http/get url0) 99 | res1 (http/get url1)] 100 | (async done 101 | (go 102 | (is (= (> 13 | 14 | == Editors 15 | 16 | * <> 17 | * <> 18 | * <> 19 | * <> 20 | * <> 21 | * <> 22 | * <> 23 | 24 | == Build Tools 25 | 26 | 27 | * <> 28 | * https://figwheel.org[figwheel] 29 | * <> 30 | * https://github.com/emezeske/lein-cljsbuild[lein-cljsbuild] 31 | -------------------------------------------------------------------------------- /content/tools/vim.adoc: -------------------------------------------------------------------------------- 1 | = Vim 2 | David Nolen 3 | 2016-08-02 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | [[paredit]] 9 | == Paredit 10 | 11 | Emacs users are used to the paredit plugin that makes it easy to keep 12 | parenthesis balanced. Vim users can get the same effect with 13 | http://www.vim.org/scripts/script.php?script_id=3998[paredit.vim]. 14 | 15 | [[multi-repl-single-environment-evaluating-forms-from-vim]] 16 | == Multi-repl, single environment, evaluating forms from Vim 17 | 18 | [[dependencies]] 19 | === Dependencies 20 | 21 | * Install Tmux 22 | * Install 23 | http://www.vim.org/scripts/script.php?script_id=3023[tslime.vim] 24 | * Install Leiningen plugin: 25 | https://github.com/franks42/lein-repls[lein-repls] 26 | * Also install the `cljsh` script on your path 27 | 28 | [[configure-lein-repl]] 29 | === Configure Lein repl 30 | 31 | In `project.clj` add: 32 | 33 | [source,clojure] 34 | ---- 35 | :repl-init myapp.repl 36 | ---- 37 | 38 | In `src/clj/myapp/repl.clj`: 39 | 40 | [source,clojure] 41 | ---- 42 | (ns myapp.repl 43 | (:use [cljs.repl.browser :only (repl-env)]) 44 | (:require [cljs.repl])) 45 | 46 | (defn repljs [] 47 | (cljs.repl/repl (repl-env))) 48 | ---- 49 | 50 | [[run-repls]] 51 | === Run repls 52 | 53 | * Open two TMux sessions in your project root directory 54 | * Run `lein repls` in one of them 55 | * This is your "server" or "macros" or "clj" repl 56 | * Run `cljsh` in the other one 57 | * This is your "client" or "cljs" repl 58 | * Eval `(repljs)` 59 | 60 | [[connect-vim]] 61 | === Connect VIM 62 | 63 | * Open two instances of Vim 64 | * One in your `src/clj` directory and one in `src/cljs` directory 65 | * Press `^c^c` in each, selecting the right TMux session when prompted 66 | -------------------------------------------------------------------------------- /content/tools/vscode.adoc: -------------------------------------------------------------------------------- 1 | = Visual Studio Code 2 | Denis Baudinot 3 | 2021-07-11 4 | :type: tools 5 | :toc: macro 6 | :icons: font 7 | 8 | https://code.visualstudio.com/[Visual Studio Code] has Clojure and ClojureScript support via the https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva[Calva] extension. 9 | 10 | From the https://calva.io/[calva documentation]: 11 | 12 | [quote] 13 | Calva is an integrated REPL powered environment for enjoyable and productive Clojure and ClojureScript development in Visual Studio Code. It includes inline code evaluation, Paredit, code formatting, a test runner, syntax highlighting, linting, and more. Calva is open source and free to use. -------------------------------------------------------------------------------- /scripts/trigger: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -XPOST -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" -H "Authorization: token $TOKEN" https://api.github.com/repos/cognitect/clojurescript-org-style/dispatches --data '{"event_type": "publish"}' 4 | --------------------------------------------------------------------------------