Liking cljdoc? Tell your friends :D

Changelog

Squint: Light-weight ClojureScript dialect

0.14.203

Preparatory release before adding immutable + persistent collections in squint.immutable tl;dr: added a lot of protocols and made sure core functions work properly with them.

  • clojure.set dispatches through the collection protocols: results keep the input's type, membership tests against a protocol set are value-based, and rename-keys/map-invert no longer mutate a record
  • Add the IStack, IIndexed, IVector, IWriter and IPrintWithWriter protocols, write-all, and an ITransientVector -pop! slot; nth, peek, pop, pop!, subvec, vec, vector?, sequential?, set?, map?, seq, = and printing dispatch to custom collection types
  • Add equiv, hash, hash-ordered-coll, hash-unordered-coll and the IHash protocol. hash follows equiv: plain mutable objects and arrays hash by reference
  • Add the IEncodeJS protocol; clj->js dispatches through it so a custom type controls its own conversion
  • Add the IMeta and IWithMeta protocols; meta and with-meta dispatch through them and the internal meta symbol property is gone
  • Add :require-global and :refer-global to ns, binding globals loaded via a script tag to consts without emitting an import
  • The CLI reports the file, line and column of a compile error and exits non-zero, instead of dumping the raw exception
  • Support :as-alias in ns :require like CLJS: no runtime import, only a compile-time alias so a namespaced keyword such as ::alias/x resolves
  • Fix iterable to reject a class instance that has no native iterator or ISeqable, so reduce, into, remove and friends no longer expose an object's internal fields, matching seqable? and CLJS
  • Fix seq of a js/Map or sorted-map to return a non-map sequence of entries, like a plain map and like CLJS, instead of the map itself
  • A collection passed in function position is callable as a lookup only if it is a vector, map, set or a type implementing ILookup. A seq, list or opaque object now throws when called through juxt, comp and friends, like a non-IFn in CLJS
  • Fix descendants to throw on a constructor, like CLJS, instead of returning nil
  • Add ident?, simple-ident?, qualified-ident?, simple-symbol?, qualified-symbol?, num, byte and short
  • Add fnext, nfirst, nthnext, nthrest, parse-boolean, char, pop!, print-str, println-str, prn-str, random-sample, float?, reversible?, / as a value and associative? through the IAssociative protocol
  • Add the ISet, IEditableCollection, ITransientCollection, ITransientAssociative, ITransientMap and ITransientSet protocols. disj, transient, conj!, assoc!, dissoc!, disj! and persistent! dispatch to them on custom types
  • Records are JS-iterable over their entries and print readably in the Node console
  • Add defrecord, record? and the IRecord marker protocol. Records store their fields as own string-keyed properties and implement the map-facing protocols, so keyword lookup, keys, seq, assoc, conj and = work through the regular core functions. assoc keeps the record type, dissoc of a basis field gives a plain map, printing gives #TypeName{:a 1}
  • The generated record implementations are shared runtime functions in squint-cljs/src/squint/record.js, imported only by files that use defrecord: each defrecord emits one attach call instead of nine method bodies
  • Fix merge on a record or other -conj type without an empty representation
  • Fix merge, keys, vals, update-keys and update-vals to dispatch through the map protocols on custom types, instead of mutating copies or reading internal properties
  • Fix into to reduce through -conj on a type implementing ICollection instead of mutating a plain copy
  • Fix assoc-in and update-in to read intermediate levels through -lookup, so nested updates work on types implementing the map protocols
  • Add the ILookup, IAssociative, IMap, ICounted, IKVReduce, ICollection, IEmptyableCollection and IEquiv protocols. get, assoc, contains?, find, dissoc, count, reduce-kv, conj, empty and = dispatch to them on custom types. Plain objects and arrays keep their fast paths

0.14.202

  • Fix assoc and assoc! called without a value for the last key: throws at runtime, and at compile time for a literal call
  • Add get-validator and set-validator!
  • Fix a def or deftype inside a function being added to the module exports, which made the module fail to load
  • Fix take-nth to throw on a non-number step instead of looping forever
  • Fix empty to return nil on non-collections and class instances instead of throwing, like CLJS
  • Fix assoc! on a vector to validate the index like assoc, instead of writing a sparse array
  • Fix parents, ancestors and descendants to return nil on an invalid hierarchy instead of throwing

0.14.201

  • The built-in protocols can be extended to nil and to base types such as number and string via extend-type
  • BREAKING: deref, reset!, swap!, add-watch and remove-watch dispatch only through the protocols. The internal _deref and _reset_BANG_ props are no longer consulted: implement IDeref, IReset, ISwap or IWatchable instead
  • Add the IReset, ISwap and IWatchable protocols, satisfied by atoms. reset!, swap!, add-watch and remove-watch dispatch to them on custom types, so a reagent-style reactive atom can be a deftype
  • Fix multi-arity and variadic deftype methods to receive this, so protocol methods with more than one arity work
  • cljs.analyzer.api/resolve at compile time now sees vars of built-in library namespaces such as clojure.string, through an alias or fully qualified
  • Add clojure.string/escape
  • Fix clojure.string/blank? to return false on a non-string instead of throwing, like CLJS
  • Fix peek to throw on a non-stack such as a set or map, like CLJS
  • Fix = to compare regexes by identity, like CLJS, so two equal regex literals are not equal
  • Fix cons to throw eagerly on a non-seqable tail such as a number, like CLJS. seq throws the same is not ISeqable error on non-seqables such as a class instance without iterator
  • Add the ISeqable protocol with -seq: a type extended to it seqs through its -seq method in seq, vec, cons and everything built on them, and seqable? returns true for it
  • Fix some-fn to return the last predicate result such as false instead of nil, and to treat 0 and "" as truthy, like CLJS
  • Fix min-key and max-key to compare pairwise like CLJS, correcting the result when keys are NaN or equal
  • Fix merge with a non-collection first arg to return it or throw on more args, like CLJS, instead of failing to copy it
  • conj and merge on a map throw when a vector arg is not a pair, like CLJS
  • Fix nth to throw on a non-number index, pop to throw on a non-stack, keys and vals to throw on a non-map, and hash-map to throw on a missing value, like CLJS
  • Fix seq to throw on a function, (conj! coll) to return the coll unchanged, and conj on a map to accept only map entries or seqables of map entries, like CLJS
  • Fix disj to preserve metadata
  • take, drop, take-last and drop-last assert a number count, like CLJS
  • Add the IAtom marker protocol and the IDeref protocol with -deref, both satisfied by atoms. deref and @ dispatch to -deref on types extended via extend-type, like CLJS
  • Add missing-protocol and throw its clear error on every protocol dispatch miss, including custom protocols, like CLJS
  • Support the :meta and :validator options of atom, like CLJS. The validator runs on reset! and swap!, not at creation, matching current CLJS behavior
  • Fix reset! to return the new value
  • Fix assoc on a vector to validate the index, like CLJS: out of bounds or a non-number key throws, index count appends. assoc on false also throws: only nil puns to an empty map
  • Fix dissoc to throw on a non-map collection such as a vector, set or list, like CLJS
  • Fix get-in and select-keys to treat a nil path or key seq as empty, like CLJS, and select-keys to always return a map
  • Fix (cycle nil) and (cycle []) to give an empty seq instead of throwing or looping, cycle a map by its entries, and throw eagerly on a non-iterable, like CLJS
  • Fix NaN? to coerce its argument like CLJS js/isNaN, so (NaN? "foo") is true
  • Add hash-set, sorted?, char?, rseq, parse-uuid, force, clojure.string/reverse and the typed array constructors int-array, long-array, float-array, double-array and object-array
  • Fix random-uuid to return a UUID instance, so uuid? is true for it, like CLJS
  • uuid lowercases its argument, like CLJS
  • doall returns the realized seq itself instead of a vector, like CLJS
  • A dotted class ref like cljs.core.UUID resolves to the core module member, like in CLJS
  • Fix = to compare a plain object map and a js/Map by entries, so the two map reps are equal when their contents are
  • derive, underive, isa?, parents, ancestors and descendants accept a hierarchy written as a plain map, like {:parents {} :ancestors {} :descendants {}}
  • BREAKING: derive and underive with an explicit hierarchy throw on a malformed one, and the global-hierarchy derive requires a namespace-qualified tag and parent, like CLJS
  • cljs.analyzer.api/resolve at compile time now sees built-in macros such as and, when-let and bit-and, and user macros, returning :macro true for them, like CLJS. A name in :refer-clojure :exclude no longer resolves to core. A local binding shadows all of these and resolves with :local true

0.14.200

  • Fix assoc! regression on non-plain objects such as a class instance or a null-prototype object
  • .indexOf on a lazy seq now uses reference equality like a JS array, not value equality. This diverges from CLJS but keeps = out of any bundle that only builds lazy seqs, shrinking a conj bundle from 3801 to 2215 bytes
  • Add :squint/compile-time opt-in mechanism for macro/compile-time namespaces. See doc/compile-time.md.
  • Fix: a macro used in the namespace that defines it (self :require-macros) now expands: the macro's own def no longer shadows the macro lookup or triggers an alias-collision rename
  • A defmacro is compile-time only: no longer emitted to the runtime module, and :refering a macro no longer emits a runtime import for it, matching CLJS
  • Fix a sorted set to compare equal by elements to a hash set or another sorted set, and give it a count
  • Fix min and max to propagate NaN like CLJS, correcting a regression in 0.14.199 where the 2-arg comparison dropped it. Also stop inlining the 2-arg call, since CLJS does not inline min/max

0.14.199

  • Fix #886: let a var shadow a same-named core macro. :refer-clojure :exclude now suppresses the core macro, and declare registers a forward reference so a core-macro-named var such as exists? resolves to the var
  • Fix min and max to compare with </> and return one of the values, so nil acts like zero and NaN propagates, like CLJS, instead of Math.min/Math.max coercing nil to 0
  • Inline the 2-arg min/max call with simple operands to a comparison, like CLJS

0.14.198

These changes were all made to improve compatibility with dialect tests in clojure-test-suite.

  • Add sorted-map, sorted-map-by and sorted-set-by, keeping entries in sorted order
  • Make subvec throw on an out-of-bounds range, a nil index or a non-vector, and coerce indices to integers, like CLJS
  • Make pop throw on an empty vector or list, like Clojure and CLJS
  • Add hash-map and array-map, both building a plain map like a map literal
  • Make even? and odd? throw on a non-integer argument, like Clojure and CLJS
  • Fix take-last to return nil for an empty or nil collection, like CLJS
  • Fix sequential? to return false for sets, maps and strings, instead of treating every iterable as sequential
  • Fix seq on a string to return its characters and on a set to return its elements, like CLJS
  • Fix peek and pop on a list to use its front, like CLJS, and (pop nil) to return nil
  • Fix keys and vals to return nil for an empty or nil map, like CLJS
  • Fix merge to return nil when called with no maps or only nil maps, like CLJS
  • Fix (partition n step pad coll) to emit the final partial partition even when pad is empty or nil, like CLJS, and no longer throw on a nil pad
  • Fix add-watch and remove-watch to return the reference, like CLJS
  • Fix cat transducer appending a nil on completion, so transduce with cat or mapcat no longer adds a trailing nil
  • Fix (conj nil) to return nil, like CLJS, instead of an empty list
  • Fix contains? on a string to test integer indices, so (contains? "abc" 0) is true, like CLJS
  • Make every lazy seq an instance of LazySeq, so (instance? LazySeq (concat ...)) and similar return true
  • Support with-meta on a lazy seq or cons, attaching metadata without forcing realization
  • Fix boolean to coerce every value except nil and false to true
  • Fix fnil to replace only nil arguments and to use per-position defaults for higher arities
  • Fix cons to compare equal to vectors and lists and to print as a list
  • Make repeat return a lazy seq, so it compares equal to vectors and lists
  • Fix unary <, >, <=, >= to return true
  • Fix = to compare js/Date values, so distinct #inst literals are not equal
  • Route output through println in cljs.test
  • Support emojis as aliases
  • Add float and double core functions
  • Fix are to substitute bindings into the test form like CLJS, so assertions such as thrown? dispatch correctly
  • Fix emission of nullary (+) and (*) and unary (- x)
  • Map clojure.core and cljs.core to the core module so they can be required, including aliased fns and macros (c/inc, c/->)
  • Fix repeatedly to return an empty seq for count 0 and throw on a non-number count
  • Add realized? for delays and lazy seqs
  • Support #uuid literals with a UUID type
  • Support #inst literals as js/Date and add inst?
  • Support extending cljs.test/assert-expr with defmethod, like CLJS

0.14.197

  • Add clojure.string/replace-first
  • Fix: user-defined function named after JS reserved word (e.g. delete) now correctly shadows the special form
  • Fix conj + SortedSet DCE issue
  • Fix #771: DCE of varargs/multi-arity functions and optimize via ... spread
  • Improve DCE of defprotocol when no :extend-via-metadata is present
  • Speed up dissoc and conj!

0.14.196

  • Add squint.edn / clojure.edn, a minimal EDN reader in 300-ish lines of JS.
  • Add *print-fn*, *print-err-fn* and *print-newline* dynamic vars, similar to CLJS
  • BREAKING: println is no longer a synonym for console.log and now prints through *print-fn* like CLJS
  • Add double?, vary-meta, symbol core fns
  • Add with-out-str
  • Add print, pr
  • Fix: coll? returned true for functions. Use aset, aget for raw property access on non-objects.
  • Make core.js more suitable for treeshaking when only a few functions from it are used.
  • pr-str and prn no longer misreport a shared reference as circular. An object referenced from two places now prints in full at each occurrence, while genuine cycles still print as #object[circular].
  • Fix thrown? to work with :default like CLJS

0.13.195

  • Fix (vec (list ..)) edge case
  • Improve inference of collections, such that (let [x {:a 1}] (x :a)) works
  • Support .indexOf on lazy seqs, matching CLJS

0.13.194

  • Replicant support. See example.
  • Support :deps in squint.edn, resolved via clojure -Spath, added to :paths implicitly. Squint only supports :git/sha and :local/root libraries for now.
  • Lazy seqs are now cached. Previously squint did not cache results so if you consumed a seq twice its results would be computed twice. For performance seqs are chunked, same as CLJS.
  • Because lazy seqs are now cached, warn-on-lazy-reusae! now prints a deprecation warning and does nothing. It will be removed in the future.
  • = compares two lazy seqs of the same type element-wise instead of as plain objects, so e.g. (= (concat nil ["a"]) (concat nil ["a"])) is true
  • persistent! no longer freezes its argument, so persistent structures stay extensible for symbol-keyed metadata
  • vswap! and vreset! return the new value, like Clojure
  • nth on an out-of-bounds index without a default now throws, like Clojure
  • disj on nil returns nil instead of throwing
  • name now returns the part after the / for a namespaced keyword/symbol (e.g. (name :foo/bar) -> "bar"), consistent with namespace so they round-trip. Since keywords are strings in squint this also applies to slash-containing strings (differs from Clojure string name).
  • namespace uses the same / threshold as name, so a leading / yields a nil namespace instead of an empty string and (str (namespace x) "/" (name x)) round-trips.
  • Add var? (always false; squint has no first-class vars)
  • Support dynamic vars and binding. An earmuffed def (e.g. *foo*) compiles to a mutable box {value ...}; references read .value, set! assigns it, and binding saves/sets/restores it. Because only the box's property is mutated (never the import binding), this works across separately-compiled ESM modules.
  • Quoted symbols now compile to strings of their name (squint has no symbol type, like keywords)
  • Syntax-quote resolves symbols against the current ns and aliases (bare -> current ns, aliased -> full ns), matching Clojure
  • defprotocol: support the :extend-via-metadata option; protocol methods fall back to an impl on the receiver's metadata keyed by the fully-qualified method name
  • :require-macros accepts a bare symbol libspec (not only a vector)
  • Macros in a .cljc/.cljs namespace required via an :as alias (without :refer) now expand (alias resolves to the macro namespace)
  • Add keyword?, simple-keyword?, qualified-keyword? (keywords are strings in squint, so these are string-based) and unchecked-int
  • Add map-entry?; map entries are tagged so they are distinguishable from plain vectors
  • Add reify
  • Add keyword, symbol?, namespace, unchecked-inc-int, unchecked-dec-int, unchecked-add-int (keywords/symbols are strings in squint)
  • Fix qualified references to a namespace alias that is shadowed by a local binding or parameter of the same name (e.g. [x.y :as r] + (let [r ...] (r/f r))); they now resolve to the full-namespace import instead of the local
  • Fix = distinguishing null from undefined; both are nil in CLJS, so (= js/undefined nil) and e.g. (= (keys nil) nil) now return true.
  • Apply reader metadata (^:foo) on vector, map, set and fn literals as runtime metadata, matching CLJS ((meta ^:foo [1 2]) -> {:foo true}). Reader location keys, compiler directives (:tag/:async/:gen) and squint-internal keys are not included; edamame now records location under :line/:column.
  • Fix = not treating sequential collections of different concrete types as equal; (= '(1 2) [1 2]) and lazy-seq/vector comparisons now return true, matching CLJS. Equal-typed collections keep their existing fast paths.
  • Fix named variadic fn whose name munges (e.g. dispatch!) emitting an invalid self-reference (dispatch!.cljs$...) in its dispatcher; the munged name is now used.
  • Fix def/defn whose name shadows a :require alias or :refer producing colliding JS identifiers (import * as foo / import { foo } + var foo). The var is now renamed to a fresh gensym and exported under its real name; a bare foo is the var, foo/bar stays the alias.
  • Add clojure.walk (walk, prewalk, postwalk, prewalk-replace, postwalk-replace, keywordize-keys, stringify-keys, and the *-demo helpers)
  • empty, conj, assoc, into and other copy-based operations now carry metadata, matching Clojure (previously metadata was dropped on the freshly built structure); with-meta/copy now also support lists
  • #html now escapes literal string attributes
  • #html now does not emit true for a boolean-true attribute, but emits bare attribute
  • #html now gates CSS output on style attribute name
  • CLI: shell tab completion via babashka.cli's hidden org.babashka.cli/completions command. Print an install snippet with e.g. squint org.babashka.cli/completions snippet --shell zsh (bash, zsh, fish, powershell and nushell are supported)
  • CLI: --help/-h, argument validation and error messages are now provided by babashka.cli's dispatch (standard Usage/Commands/Options help, errors to stderr). Builds on #691 (@lread)

0.12.193

  • Fix #832: nREPL server hung on advertised ops. info/eldoc/lookup, complete (including js/ interop completion) and load-file are now implemented.
  • Fix parse-long returning out-of-range values instead of nil (the safe-integer upper bound was a no-op due to a chained comparison)
  • Fix select-keys dropping keys mapped to nil (loose != undefined matched null); nil-valued keys are now kept, matching Clojure
  • Fix clojure.string/split limit semantics: a positive limit now caps the number of splits and keeps the remainder (e.g. (str/split "a-b-c-d" #"-" 2) -> ["a" "b-c-d"]) instead of truncating like JS String.split; limit 0 discards trailing empties, negative keeps them
  • Fix compare throwing on booleans; (compare false true) -> -1 and (sort [true false]) no longer throws, matching CLJS
  • clojure.set/intersection and union now use .size (not .length) for their set-size optimization, which was previously dead code (undefined > undefined); results were already correct, this restores the intended performance
  • Fix seqable? returning false for maps; (seqable? {:a 1}) -> true, matching CLJS (seq already worked on objects)
  • Fix nth returning the not-found default for an in-bounds element that is undefined (e.g. sparse / object-array / JS-interop arrays); it now decides found-ness by the index bound, not the value
  • Fix parse-double not trimming leading/trailing whitespace ((parse-double " 3.14 ") -> 3.14); the whitespace character class in the regexes was double-escaped and matched literal backslashes instead of control chars
  • pr-str / prn now print Infinity, -Infinity and NaN as ##Inf, ##-Inf and ##NaN, matching CLJS (str is unchanged)

0.12.192

  • Add support for Vite 5-8

0.12.191

  • Add dedupe (seq and transducer arities)
  • Add distinct?, any?, ifn?, list*
  • Fix #819: macro changes not picked up in watch mode. The persistent compiler now re-evaluates a macro namespace when its source file changes (mtime + sha256 gate), instead of keeping the first-loaded definitions.
  • REPL: print promises as #<Promise 1> / #<Promise rejected ..> / #<Promise pending> instead of silently unwrapping them. Also surfaces a Promise wrapper in the playground (resolved value still inspectable).

0.12.190

  • Browser nREPL support. See docs
  • Fix #815: str wrapping known-numeric infix expressions in ??'', which esbuild flagged as suspicious-nullish-coalescing. (@willcohen)
  • Fix #820: :macros option silently ignored when passed to compileString / compileStringEx from JavaScript callers (string keys were keyword-ized by clj-ize-opts and no longer matched the symbol-keyed macro lookups in compile*). (@willcohen)

0.11.189

  • #809: add squint.compiler/compile* and squint.compiler/transpile* which accept either a string or a sequence of pre-parsed forms, skipping the forms -> string -> forms roundtrip for SSR use cases. The previous names compile-string* / transpile-string* are retained as deprecated aliases.
  • Fix #810: shorthand classes in #html / #jsx were erased when an attrs map was present without a :class key (e.g. [:div.myclass {}]).

0.11.188

  • Add multimethod support (#806): defmulti, defmethod, get-method, methods, remove-method, remove-all-methods, prefer-method, prefers, and hierarchy ops isa?, derive, underive, make-hierarchy, parents, ancestors, descendants.

  • cljs.test/report is now a multimethod, extensible via defmethod:

    (defmethod report [:cljs.test/default :begin-test-var] [m] ...)
    

    test-var now fires :begin-test-var / :end-test-var events.

0.11.187

  • Accept plain await in async functions, in anticipation of CLJS next. The legacy js-await and js/await forms continue to work as aliases for now and may be deprecated in a future version.
  • Add built-in cljs.test / clojure.test support: deftest, is, testing, are, use-fixtures, async, run-tests.
  • Fix with-meta now preserves callability when applied to a function
  • Fix #783: auto-load macros from .cljc files via :require (no need for :require-macros)
  • Fix #783: resolve qualified symbols from macro expansions
  • Fix #784: resolve transitive macro deps and auto-import runtime deps from macro expansion
  • Fix #786: resolve-macro-ns for cherry namespace resolution

v0.10.186 (2026-03-07)

  • Fix #799: forgot to add squint.math file to package.json

v0.10.185 (2026-01-26)

  • Fix emitting negative zero value (-0.0)
  • Add squint.math, also available as clojure.math namespace (a direct port of the original)

v0.9.184

  • Fix #792: prn js/undefined as nil
  • Fix #793: fix yield* IIFE (needs wrapping in parens)

v0.9.183

  • #779: Added compare-and-swap!, swap-vals! and reset-vals! (@tonsky)
  • #788: Fixed compilation of dotimes with _ binding (@tonsky)
  • #790: Fixed shuffle not working on lazy sequences (@tonsky)
  • Multiple :require-macros with :refer now accumulate instead of overwriting (@willcohen)

v0.9.182

  • Allow macro namespaces to load "node:fs", etc. to read config files for conditional compilation
  • Don't emit IIFE for top-level let so you can write let over defn to capture values.

v0.9.181

  • Fix js-yield and js-yield* in expression position
  • Implement some? as macro

v0.9.180

  • Fix #758: volatile!, vswap!, vreset!
  • pr-str, prn etc now print EDN (with the idea that you can paste it back into your program)
  • new #js/Map reader that reads a JavaScript Map from a Clojure map (maps are printed like this with pr-str too)

v0.9.178

  • Support passing keyword to mapv
  • #759: doseq can't be used in expression context
  • Fix #753: optimize output of dotimes
  • alength as macro

v0.9.177

  • Inline identical? calls
  • Clean up emissiong of paren wrapping
  • Add nat-int?, neg-int?, pos-int? (@eNotchy)
  • Add rand

v0.9.176

  • Fix rendering of null and undefined in #html

v0.9.175

  • #747: #html escape fix

v0.9.174

  • Optimize nested assoc calls, e.g. produced with ->
  • Avoid object spread when object isn't shared (auto-transient)

v0.9.173 (2025-10-19)

  • Optimize str even more

v0.9.172 (2025-10-19)

Remove debug output from compilation

v0.9.171 (2025-10-19)

  • Optimize =, and, and not= even more

v0.9.170 (2025-10-19)

  • not= on undefined and false should return true

v0.9.169 (2025-10-18)

  • Optimize code produced for assoc, assoc! and get when object argument can be inferred or is type hinted with ^object
  • Optimize str using macro that compiles into template strings + ?? '' for null/undefined
  • Fix #732: take-last should return nil or empty seq for negative numbers

v0.8.159 (2025-10-13)

  • #725: keys and vals should work on js/Map

v0.8.158 (2025-10-10)

  • Make map-indexed and keep-indexed lazy

v0.8.157 (2025-10-08)

  • Compile time optimization for = when using it on numbers, strings or keyword literals

News

Cljdoc chose squint for its small bundle sizes and easy migration off of TypeScript towards CLJS

v0.8.156 (2025-10-07)

  • Switch = to a deep-equals implementation that works on primitives, objects, Arrays, Maps and Sets

v0.8.155 (2025-10-02)

  • Fix #710: add parse-double
  • Fix #714: assoc-in on nil or undefined
  • Fix #714: dissoc on nil or undefined

v0.8.154 (2025-09-19)

  • Basic :import-maps support in squint.edn (just literal replacements, prefixes not supported yet)

v0.8.153 (2025-08-31)

  • Fix #704: while didn't compile correctly
  • Add clojure.string/includes?
  • Emit less code for varargs functions
  • Fix solidJS example
  • Documentation improvements (@lread)
  • Fix #697: ClassCastException in statement function when passed Code records

v0.8.152 (2025-07-18)

  • Fix #680: support import attributes using :with option in require, e.g. :with {:type :json}

v0.8.151 (2025-07-15)

  • Implement not= as function
  • Fix #684: JSX output

v0.8.150 (2025-07-09)

v0.8.149 (2025-06-19)

  • #671: Implement trampoline (@rafaeldelboni)
  • Fix #673: remove experimental atom as promise option since it causes unexpected behavior
  • Fix #672: alias may contain dots

v0.8.148 (2025-05-25)

  • Fix #669: munge refer-ed + renamed var

v0.8.147 (2025-05-09)

  • Fix #661: support throw in expression position
  • Fix #662: Fix extending protocol from other namespace to nil
  • Better solution for multiple expressions in return context in combination with pragmas
  • Add an ajv example

v0.8.146

  • #653: respect :context expr in compile-string
  • #657: respect :context expr in set! expression
  • #659: fix invalid code produced for REPL mode with respect to return

v0.8.145 (2025-04-11)

  • #651 Support :require + :rename + allow renamed value to be used in other :require clause

v0.8.144 (2025-04-09)

  • Fix #649: reset ns when compiling file and fix initial global object

v0.8.143 (2025-04-07)

  • Fix #647: emit explicit null when written in else branch of if

v0.8.142 (2025-03-19)

v0.8.141 (2025-03-10)

  • Fix #602: support hiccup-style shorthand for id and class attributes in #jsx and #html

v0.8.140 (2025-03-09)

v0.8.139 (2025-03-04)

  • defclass: elide constructor when not provided

v0.8.138 (2025-03-04)

  • Fix #603: don't emit multiple returns
  • Drop constructor requirement for defclass

v0.8.137 (2025-02-28)

  • Fix #626: Implement take-last
  • Fix #615: (zero? "0") should return false
  • Fix #617: deftype field name munging problem
  • Fix #618: Named multi-arity fn args don't get munged (@grayrest)
  • Fix #622: operator precendence issue with | and if
  • Add clojure.string functions lower-case, upper-case, capitalize (@plexus)

v0.8.136 (2024-02-21)

  • Fix #609: make remove return a transducer when no collection is provided
  • Fix #611: Implement the set? function (@jonasseglare)
  • Fix #613: Optimize aset

v0.8.134 (2024-02-11)

  • Fix #605: merge command line --paths with squint.edn config properly
  • Fix #607: make mapcat return a transducer if no collections are provided (@jonasseglare)

v0.8.132 (2024-12-29)

  • Fix #255: fn literal with rest args

v0.8.131 (2024-12-21)

  • #596: fix unary division to produce reciprocal

v0.8.129 (2024-12-03)

  • #592: fix clj->js to not process custom classes

v0.8.128 (2024-12-02)

  • #585: fix clj->js to realize lazy seqs into arrays

v0.8.127 (2024-11-29)

  • #586: support extending protocol to nil

v0.8.125 (2024-11-28)

  • #581: support docstring in defprotocol
  • #582: add extend-protocol

v0.8.124 (2024-11-20)

  • Add delay
  • Fix #575: map? should not return true for array
  • Fix #577: support $default + :refer

v0.8.123 (2024-11-05)

  • Fix #572: prevent vite page reload

v0.8.122 (2024-10-19)

  • Fix watcher and compiler not overriding squint.edn configurations with command line options, take 2

v0.8.121 (2024-10-18)

  • Fix watcher and compiler not overriding squint.edn configurations with command line options.

v0.8.120 (2024-10-18)

  • Fix watcher not being called

v0.8.119 (2024-10-18)

  • Allow passing --extension and --paths via CLI

v0.8.118 (2024-10-17)

  • Fix #563: prioritize refer over core built-in
  • Update chokidar to v4 which reduces the number of dependencies

v0.8.117 (2024-10-11)

  • BREAKING: Dynamic CSS in #html must now be explicitly passed as map literal: (let [m {:color :green}] #html [:div {:style {:& m}}]). Fixes issue when using lit-html in combination with classMap. See demo

v0.8.116 (2024-10-05)

  • #556: fix referring to var in other namespace via global object in REPL mode

v0.8.115 (2024-10-01)

  • Pass --repl opts to watch subcommand in CLI

v0.8.114 (2024-09-23)

  • #552: fix REPL output with hyphen in ns name

v0.8.113

  • #542: fix run on Windows

v0.8.112

  • #536: HTML is not escaped in dynamic expression

v0.7.111

  • #537: Fix not: wrap argument in parens
  • Return interop expression in function body

v0.7.110

  • Prefer value from props map over explicit value

v0.7.109

  • #html improvements, support :& for spreading props

v.0.7.108

  • #492: defclass static methods and fields
  • #526: Fix export of class name with dashes

v0.7.107

  • #517: Preserve state over REPL evals

v0.7.106 (2024-05-02)

  • #513: Fix shuffle core function random distribution and performances
  • #517: Fix re-definition of class with defclass in REPL
  • #522: fix nil #html rendering issue

v0.7.105 (2024-04-15)

  • #509: Optimization: use arrow fn for implicit IIFE when possible
  • Optimization: emit const in let expressions, which esbuild optimizes better

v0.7.104 (2024-04-05)

  • Don't wrap arrow function in parens, see this issue

v0.7.103 (2024-04-05)

  • Fix #499: add support for emitting arrow functions with ^:=> metadata

v0.7.102 (2024-04-03)

  • Fix #505: Support :rename in :require

v0.7.101 (2024-04-02)

  • Fix #490: render css maps in html mode
  • Fix #502: allow method names in defclass to override squint built-ins

v0.7.100 (2024-03-29)

  • Fix #496: don't wrap strings in another set of quotes

v0.7.99 (2024-03-29)

  • Fix rendering of attribute expressions in HTML (should be wrapped in quotes)

v0.7.98 (2024-03-25)

  • Compile destructured function args to JS destructuring when annotated with ^:js. This benefits working with vitest and playwright.

v0.7.97 (2024-03-25)

  • #481: BREAKING, squint no longer automatically copies all non-compiled files to the :output-dir. This behavior is now explicit with :copy-resources, see docs.

v0.7.96 (2024-03-14)

  • Add new #html reader for producing HTML literals using hiccup. See docs and playground example.
  • #483: Fix operator precedence problem

v0.6.95 (2024-02-26)

  • #472: Use consistent alias
  • #474: fix JSX fragment
  • #475: don't crash watcher on deleting file

v0.6.94 (2024-02-20)

  • Add simple-benchmark

v0.6.93 (2024-02-16)

  • #468: Keywords in JSX should render with hyphens

v0.6.92 (2024-02-15)

  • #466: Fix doseq expression with set! in function return position

v0.6.91 (2024-02-14)

  • #462: Add "exports" field to package.json
  • #460: escape < and > in JSX strings

v0.6.90 (2024-02-06)

  • #458: don't emit null in statement position

v0.6.89 (2024-02-01)

  • #455: don't export non-public vars

v0.6.88 (2024-01-10)

  • Fix infix operator in return position
  • Allow playground to use JSX in non-REPL mode

v0.6.87 (2024-01-06)

  • Add transducer arity to all existing core functions

v0.5.86 (2023-12-23)

  • Support ^:gen + js-yield + js-yield* to write JS generator functions. See playground
  • Add update-keys and update-vals
  • Add = as reified function

v0.4.85 (2023-12-20)

  • #449: fix issue with :refer

v0.4.84 (2023-12-19)

  • Add memoize, filter transducer arity, peek, pop
  • Export classes defined with defclass
  • Support ^:async Object method in defclass

v0.4.83 (2023-12-16)

  • Better support for pragmas and JSDoc via js* + // and /* */
  • Add rem, nnext, str/end-with?, str/index-of and str/last-index-of
  • Fix alias with hypen in REPL mode

v0.4.82 (2023-12-14)

  • Keep top level strings and comments (via js*) before imports (for JSDoc, Next.js "use client", etc)

v0.4.81 (2023-12-11)

  • Fix compileString in JS API

v0.4.80 (2023-12-11)

  • Optimization: sort largest set first for set/union, and smallest first for set/intersection
  • Add sorted-set, long, abs, keep-indexed transducer arity

v0.4.79 (2023-12-09)

  • The children function in tree-seq may return nil

v0.4.78 (2023-12-09)

  • Add clojure.set/join
  • Add tree-seq, flatten, seq? and sequential?

0.4.77 (2023-12-09)

  • Add clojure.set functions select, rename-keys, rename, project, and map-invert (@PEZ)
  • Fix reduce-kv with js/Map input

0.4.76 (2023-12-07)

  • Add more clojure.set functions: difference, union, subset?, and superset? (@PEZ)

0.4.75 (2023-12-07)

  • Let any object that has Symbol.iterable be destructureable even if it is not instance of Object

0.4.74 (2023-12-07)

  • Initial version of clojure.set
  • #418: Add reductions
  • Add bit-shift-left and more bit- related macros
  • Fix not with respect to truthiness
  • Fix reduce without initial value + empty coll, it should call f()
  • Add serve-playground bb task
  • Update playground with button for creating a blank AOC playground

0.4.73 (2023-12-05)

  • #407: fix conditional rendering
  • Add not-empty
  • Fix into + set + xform

0.4.72 (2023-12-04)

  • Allow JSX to be used in playground. See react example.
  • Add re-pattern (fixes #396)
  • Add zipmap

0.4.71 (2023-12-02)

  • More helpful error from JS when using unresolved symbol in REPL mode

0.4.70 (2023-12-02)

  • Allow >, < etc to be used as HOFs
  • Fix str/split with respect to trailing empty split elements

0.4.69 (2023-12-02)

  • Fix vararg functions in REPL mode

0.4.68 (2023-12-01)

  • #394: add int
  • #393: Math can be used without js/ prefix
  • Expose compiler state via compileStringEx for playground, preserves namespace transitions

0.4.67 (2023-11-28)

  • Restore backward compatibility with code that is compiled with older versions of squint

0.4.66 (2023-11-28)

  • Optimize various outputs for smaller size
  • Add js-in

0.4.65 (2023-11-28)

  • Support into + xform

0.4.64 (2023-11-27)

  • Support sort on strings

0.4.63 (2023-11-26)

  • #386: allow expression in value position in map literal

0.4.62 (2023-11-25)

  • Improvements with respect to laziness in mapcat and concat
  • Do not array mutate argument in reverse

0.4.61 (2023-11-25)

  • Escape JSX attribute vector value (and more)

0.4.60 (2023-11-24)

  • map + transduce support
  • Fix for in REPL mode
  • Throw when object is not iterable in for
  • Make next lazy when input is lazy
  • Fix playground shim (fixes issue in older versions of Safari)

0.4.59 (2023-11-23)

  • Add js-mod and quot

0.4.58 (2023-11-22)

  • #380: Don't emit space in between #jsx tags
  • Add re-find

0.4.57 (2023-11-21)

  • Add condp macro

0.4.56 (2023-11-20)

  • Use compare as default compare function in sort (which fixes numerical sorting)

0.4.55 (2023-11-20)

  • Allow assoc! to be called on arbitrary classes (regression)

0.4.54 (2023-11-19)

  • Improve get to call get method when present.

0.4.53 (2023-11-19)

  • False alarm, I was playing the pinball game in low power mode on my mobile 🤦

0.4.52 (2023-11-19)

  • Revert truthiness checks via funcall, negative impact on performance with pinball game on mobile

0.4.51 (2023-11-18)

  • Allow keywords and collections to be used as functions in HOFs
  • Make filter, etc aware of truthiness
  • Reduce code size for truthiness checks

0.4.50 (2023-11-18)

  • Add str/split-lines
  • Add partition-by
  • Add parse-long
  • Add sort-by

0.4.49 (2023-11-18)

  • Fix top level await

0.4.48 (2023-11-17)

  • Support multiple dimensions in aset
  • Add coercive-= as alias for ==
  • Add js-delete

0.4.47 (2023-11-17)

  • Fix min-key and max-key and improve tests

0.4.46 (2023-11-16)

  • Add min-key and max-key
  • Fix defonce in REPL-mode

0.4.45 (2023-11-16)

  • Fix doseq and for when binding name clashes with core var

0.4.44 (2023-11-15)

  • No-op release to hopefully fix caching issue with jspm

0.4.43 (2023-11-15)

0.4.42 (2023-11-13)

  • Allow alias name to be used as object in REPL mode

0.4.41 (2023-11-12)

  • Copy resources when using squint compile or squint watch

0.4.40 (2023-11-12)

  • Return map when select-keys is called with nil
  • nREPL server: print values through cljs.pprint (@PEZ)

0.4.39 (2023-11-10)

  • Initial (incomplete!) nREPL server on Node.js: npx squint nrepl-server :port 1888
  • Update/refactor threejs example

0.3.38 (2023-11-07)

  • #360: assoc-in! should not mutate objects in the middle if they already exist
  • Evaluate lazy-seq body just once
  • Avoid stackoverflow with min and max
  • #360: fix assoc-in! with immutable objects in the middle
  • Add mod, object?
  • Optimize get
  • Add threejs example

0.3.37 (2023-11-05)

  • #357: fix version in help text
  • Fix iterating over objects
  • Add clojure.string's triml, trimr, replace
  • Fix examples/vite-react by adding public/index.html
  • Add find, bounded-count, boolean?, merge-with, meta, with-meta, int?, ex-message, ex-cause, ex-info
  • Fix munging of reserved symbols in function arguments

0.3.36 (2023-10-31)

  • #350: js* should default to :context :expr
  • #352: fix zero? in return position
  • Add NaN? (@sher)

0.3.35 (2023-10-25)

  • #347: Add :pre and :post support in fn
  • Add number?
  • Support docstring in def

0.3.34 (2023-10-24)

  • Handle multipe source :paths in a more robust fashion

0.3.33 (2023-10-24)

  • #344: macros can't be used via aliases

0.3.32 (2023-10-17)

  • Add squint.edn support, see docs
  • Add watch subcommand to watch :paths from squint.edn
  • Make generated let variable names in JS more deterministic, which helps hot reloading in React
  • Added a vite + react example project.
  • Resolve symbolic namespaces (:require [foo.bar]) from :paths

0.2.31 (2023-10-09)

  • Add bit-and and bit-or

0.2.30 (2023-10-04)

  • Include lib/squint.core.umd.js which defines a global squint.core object (easy to use in browsers, see docs)

0.2.29 (2023-10-03)

  • Add subs, fn?, re-seq
  • Add squint.edn with :paths to resolve macros from (via :require-macros)

0.2.28 (2023-09-18)

  • Fix and and or with respect to CLJS truthiness

0.2.27 (2023-09-18)

  • Respect CLJS truth semantics: only null, undefined and false are non-truthy, 0 and "" are truthy.
  • Fix dotimes

0.2.26 (2023-09-17)

  • squint repl improvements

0.2.25 (2023-09-17)

  • Do not resolve binding in catch to core var
  • Fix reading .cljc files
  • Allow passing JS object as opts in JavaScript API's compileString

0.2.24 (2023-09-13)

  • Fix instance? in return position
  • to-array, str/starts-with?

0.1.23

  • Support next on non-arrays
  • Add compare

0.1.22

  • Fix #325: fix varargs destructuring
  • Fix #326: bun compatibility

0.1.21

  • Fix into-array

0.1.20

  • Add into-array, some-fn, keep-indexed
  • Fix for lazy-seq when body returns nil

0.1.19

  • Add max, min, every-pred

0.1.18

  • Add reduce-kv

0.1.17

  • #320: fix overriding core vars

0.1.16

  • Add rand-nth, aclone, add-watch, remove-watch

0.1.15

0.0.14

  • Drop cherry core from NPM package (cruft from porting cherry to squint)

0.0.13

  • Fix compilation of empty list
  • Fix and and or without arguments
  • #308: doseq in return position emits invalid code

0.0.12

  • Add js-obj

0.0.11

0.0.10

  • #289: support :as alias with hyphen in namespace require libspec

0.0.9

  • #286: make dissoc work with multiple keys

0.0.8

  • #284: fix undefined keys/values when passing objects and maps to conj

0.0.7

  • #274: fix logic precedence by wrapping in parens

0.0.6

Add preliminary Node.js API in node.js

0.0.5

  • Support {:& more :foo :bar} syntax in JSX to spread the more map into the props, inspired by helix

0.0.4

  • Add zero? pos? and neg? core functions

0.0.3

  • Fix boolean core function export

0.0.2

  • Escape boolean in JSX attribute
  • Add boolean core function

0.0.1

  • Fix + symbol import by bumping shadow-cljs
  • Move @babel/preset-react dependency to dev dependency

0.0.0-alpha.52

  • Fix async/await + variadiac arguments
  • Fix namespaced component in JSX

0.0.0-alpha.51

  • Change default extension back to .mjs. Use --extension js to change this to .js.

0.0.0-alpha.50

  • Fix rendering of number attributes in JSX

0.0.0-alpha.49

  • Support --extension option to set extension for JS files
  • Change default extension from .mjs to .js

Can you improve this documentation? These fine people already did:
Michiel Borkent, Peter Strömberg, jonasseglare, Rafael Delboni, Nikita Prokopov, Will Cohen, Phil Baker, Arne Brasseur, Brandon Stubbs, Karl Guertin, Clément, zachcp, Cora Sutton, Jack Rusher & Alex Davis
Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close