Squint: Light-weight ClojureScript dialect
- Fix #985: munge JS reserved words on the JVM compiler path
- Fix core var references in macro expansions on the JVM compiler path
- Fix let rename collisions in REPL output
- Fix "invalid form" error for expanded call forms on the JVM compiler path
- Fix repeated REPL
requirethrowing on aliases from earlier evals - Fix REPL
requireof squint.core registering an unbound alias - Resolve core ns aliases to core vars
- Use
Symbol.forfor protocol method dispatch, so pulling in multiple copies of squint.core (e.g. via http://esm.sh/) does not break protocol dispatch
- Clojure 1.13 destructuring:
:keys!/:syms!/:strs!for required keys,&inside them for keys required but not bound,:select,:all,:defaults, and:orby key. Addsreq!andsome-valsto core - Fix #975:
& {:keys [...]}now destructures a map instead of the raw rest args, and a seq destructured as a map is read as kwargs. Both the kwargs and trailing-map call styles work, viaseq-to-map-for-destructuring. - Fix #977:
recurinsidetryno longer emits an illegalcontinue. Atryin return position emits without the iife wrapper that cut therecuroff from its loop - Fix #978:
defclassnow supports^:getand^:setmethods defmultinow defines the multimethod withdefoncein REPL-mode, so a REPL or vite HMR module reload keeps the registered methods- Share the macro scan and macro lookup with cherry. A macro expansion calling another macro namespace's macro fully qualified now expands instead of compiling to a runtime call
- Fix #960: the nREPL server no longer logs requests, responses and eval errors by default. Enable with
--debug(CLI),:debugin squint.edn, or:debug(startServer) - DCE and performance optimizations in core lib
- Fix #957: vite HMR: support
^:dev/after-load+^:dev/before-loadhooks similar to shadow-cljs - REPL mode: resolve local namespace aliases and refers through
globalThisso redefined and hot-swapped code stays visible across namespaces. The REPL now expects:repl-compiled output.
- Fix #955: cross-ns extend-type keys impl by protocol slot Symbol
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.setdispatches through the collection protocols: results keep the input's type, membership tests against a protocol set are value-based, andrename-keys/map-invertno longer mutate a record- Add the
IStack,IIndexed,IVector,IWriterandIPrintWithWriterprotocols,write-all, and anITransientVector-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-colland theIHashprotocol.hashfollowsequiv: plain mutable objects and arrays hash by reference - Add the
IEncodeJSprotocol;clj->jsdispatches through it so a custom type controls its own conversion - Add the
IMetaandIWithMetaprotocols;metaandwith-metadispatch through them and the internal meta symbol property is gone - Add
:require-globaland:refer-globaltons, 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-aliasinns:requirelike CLJS: no runtime import, only a compile-time alias so a namespaced keyword such as::alias/xresolves - Fix
iterableto reject a class instance that has no native iterator orISeqable, soreduce,into,removeand friends no longer expose an object's internal fields, matchingseqable?and CLJS - Fix
seqof ajs/Mapor 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 throughjuxt,compand friends, like a non-IFn in CLJS - Fix
descendantsto throw on a constructor, like CLJS, instead of returning nil - Add
ident?,simple-ident?,qualified-ident?,simple-symbol?,qualified-symbol?,num,byteandshort - Add
fnext,nfirst,nthnext,nthrest,parse-boolean,char,pop!,print-str,println-str,prn-str,random-sample,float?,reversible?,/as a value andassociative?through theIAssociativeprotocol - Add the
ISet,IEditableCollection,ITransientCollection,ITransientAssociative,ITransientMapandITransientSetprotocols.disj,transient,conj!,assoc!,dissoc!,disj!andpersistent!dispatch to them on custom types - Records are JS-iterable over their entries and print readably in the Node console
- Add
defrecord,record?and theIRecordmarker protocol. Records store their fields as own string-keyed properties and implement the map-facing protocols, so keyword lookup,keys,seq,assoc,conjand=work through the regular core functions.assockeeps the record type,dissocof 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
mergeon a record or other -conj type without an empty representation - Fix
merge,keys,vals,update-keysandupdate-valsto dispatch through the map protocols on custom types, instead of mutating copies or reading internal properties - Fix
intoto reduce through-conjon a type implementingICollectioninstead of mutating a plain copy - Fix
assoc-inandupdate-into read intermediate levels through-lookup, so nested updates work on types implementing the map protocols - Add the
ILookup,IAssociative,IMap,ICounted,IKVReduce,ICollection,IEmptyableCollectionandIEquivprotocols.get,assoc,contains?,find,dissoc,count,reduce-kv,conj,emptyand=dispatch to them on custom types. Plain objects and arrays keep their fast paths
- Fix
assocandassoc!called without a value for the last key: throws at runtime, and at compile time for a literal call - Add
get-validatorandset-validator! - Fix a
defordeftypeinside a function being added to the module exports, which made the module fail to load - Fix
take-nthto throw on a non-number step instead of looping forever - Fix
emptyto return nil on non-collections and class instances instead of throwing, like CLJS - Fix
assoc!on a vector to validate the index likeassoc, instead of writing a sparse array - Fix
parents,ancestorsanddescendantsto return nil on an invalid hierarchy instead of throwing
- The built-in protocols can be extended to
niland to base types such asnumberandstringviaextend-type - BREAKING:
deref,reset!,swap!,add-watchandremove-watchdispatch only through the protocols. The internal_derefand_reset_BANG_props are no longer consulted: implementIDeref,IReset,ISwaporIWatchableinstead - Add the
IReset,ISwapandIWatchableprotocols, satisfied by atoms.reset!,swap!,add-watchandremove-watchdispatch to them on custom types, so a reagent-style reactive atom can be adeftype - Fix multi-arity and variadic
deftypemethods to receivethis, so protocol methods with more than one arity work cljs.analyzer.api/resolveat compile time now sees vars of built-in library namespaces such asclojure.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
peekto 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
consto throw eagerly on a non-seqable tail such as a number, like CLJS.seqthrows the sameis not ISeqableerror on non-seqables such as a class instance without iterator - Add the
ISeqableprotocol with-seq: a type extended to it seqs through its-seqmethod inseq,vec,consand everything built on them, andseqable?returns true for it - Fix
some-fnto return the last predicate result such asfalseinstead ofnil, and to treat0and""as truthy, like CLJS - Fix
min-keyandmax-keyto compare pairwise like CLJS, correcting the result when keys areNaNor equal - Fix
mergewith a non-collection first arg to return it or throw on more args, like CLJS, instead of failing to copy it conjandmergeon a map throw when a vector arg is not a pair, like CLJS- Fix
nthto throw on a non-number index,popto throw on a non-stack,keysandvalsto throw on a non-map, andhash-mapto throw on a missing value, like CLJS - Fix
seqto throw on a function,(conj! coll)to return the coll unchanged, andconjon a map to accept only map entries or seqables of map entries, like CLJS - Fix
disjto preserve metadata take,drop,take-lastanddrop-lastassert a number count, like CLJS- Add the
IAtommarker protocol and theIDerefprotocol with-deref, both satisfied by atoms.derefand@dispatch to-derefon types extended viaextend-type, like CLJS - Add
missing-protocoland throw its clear error on every protocol dispatch miss, including custom protocols, like CLJS - Support the
:metaand:validatoroptions ofatom, like CLJS. The validator runs onreset!andswap!, not at creation, matching current CLJS behavior - Fix
reset!to return the new value - Fix
assocon a vector to validate the index, like CLJS: out of bounds or a non-number key throws, indexcountappends.assoconfalsealso throws: onlynilpuns to an empty map - Fix
dissocto throw on a non-map collection such as a vector, set or list, like CLJS - Fix
get-inandselect-keysto treat anilpath or key seq as empty, like CLJS, andselect-keysto 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 CLJSjs/isNaN, so(NaN? "foo")is true - Add
hash-set,sorted?,char?,rseq,parse-uuid,force,clojure.string/reverseand the typed array constructorsint-array,long-array,float-array,double-arrayandobject-array - Fix
random-uuidto return aUUIDinstance, souuid?is true for it, like CLJS uuidlowercases its argument, like CLJSdoallreturns the realized seq itself instead of a vector, like CLJS- A dotted class ref like
cljs.core.UUIDresolves to the core module member, like in CLJS - Fix
=to compare a plain object map and ajs/Mapby entries, so the two map reps are equal when their contents are derive,underive,isa?,parents,ancestorsanddescendantsaccept a hierarchy written as a plain map, like{:parents {} :ancestors {} :descendants {}}- BREAKING:
deriveandunderivewith an explicit hierarchy throw on a malformed one, and the global-hierarchyderiverequires a namespace-qualified tag and parent, like CLJS cljs.analyzer.api/resolveat compile time now sees built-in macros such asand,when-letandbit-and, and user macros, returning:macro truefor them, like CLJS. A name in:refer-clojure :excludeno longer resolves to core. A local binding shadows all of these and resolves with:local true
- Fix
assoc!regression on non-plain objects such as a class instance or a null-prototype object .indexOfon 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 aconjbundle from 3801 to 2215 bytes- Add
:squint/compile-timeopt-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
defmacrois 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
minandmaxto propagateNaNlike 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 inlinemin/max
- Fix #886: let a var shadow a same-named core macro.
:refer-clojure :excludenow suppresses the core macro, anddeclareregisters a forward reference so a core-macro-named var such asexists?resolves to the var - Fix
minandmaxto compare with</>and return one of the values, sonilacts like zero andNaNpropagates, like CLJS, instead ofMath.min/Math.maxcoercingnilto0 - Inline the 2-arg
min/maxcall with simple operands to a comparison, like CLJS
These changes were all made to improve compatibility with dialect tests in clojure-test-suite.
- Add
sorted-map,sorted-map-byandsorted-set-by, keeping entries in sorted order - Make
subvecthrow on an out-of-bounds range, anilindex or a non-vector, and coerce indices to integers, like CLJS - Make
popthrow on an empty vector or list, like Clojure and CLJS - Add
hash-mapandarray-map, both building a plain map like a map literal - Make
even?andodd?throw on a non-integer argument, like Clojure and CLJS - Fix
take-lastto returnnilfor an empty ornilcollection, like CLJS - Fix
sequential?to returnfalsefor sets, maps and strings, instead of treating every iterable as sequential - Fix
seqon a string to return its characters and on a set to return its elements, like CLJS - Fix
peekandpopon a list to use its front, like CLJS, and(pop nil)to returnnil - Fix
keysandvalsto returnnilfor an empty ornilmap, like CLJS - Fix
mergeto returnnilwhen called with no maps or onlynilmaps, like CLJS - Fix
(partition n step pad coll)to emit the final partial partition even whenpadis empty ornil, like CLJS, and no longer throw on anilpad - Fix
add-watchandremove-watchto return the reference, like CLJS - Fix
cattransducer appending anilon completion, sotransducewithcatormapcatno longer adds a trailingnil - Fix
(conj nil)to returnnil, like CLJS, instead of an empty list - Fix
contains?on a string to test integer indices, so(contains? "abc" 0)istrue, like CLJS - Make every lazy seq an instance of
LazySeq, so(instance? LazySeq (concat ...))and similar returntrue - Support
with-metaon a lazy seq or cons, attaching metadata without forcing realization - Fix
booleanto coerce every value exceptnilandfalsetotrue - Fix
fnilto replace onlynilarguments and to use per-position defaults for higher arities - Fix
consto compare equal to vectors and lists and to print as a list - Make
repeatreturn a lazy seq, so it compares equal to vectors and lists - Fix unary
<,>,<=,>=to returntrue - Fix
=to comparejs/Datevalues, so distinct#instliterals are not equal - Route output through
printlnincljs.test - Support emojis as aliases
- Add
floatanddoublecore functions - Fix
areto substitute bindings into the test form like CLJS, so assertions such asthrown?dispatch correctly - Fix emission of nullary
(+)and(*)and unary(- x) - Map
clojure.coreandcljs.coreto the core module so they can be required, including aliased fns and macros (c/inc,c/->) - Fix
repeatedlyto return an empty seq for count0and throw on a non-number count - Add
realized?for delays and lazy seqs - Support
#uuidliterals with aUUIDtype - Support
#instliterals asjs/Dateand addinst? - Support extending
cljs.test/assert-exprwithdefmethod, like CLJS
- 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+SortedSetDCE issue - Fix #771: DCE of varargs/multi-arity functions and optimize via
...spread - Improve DCE of defprotocol when no
:extend-via-metadatais present - Speed up
dissocandconj!
- 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:
printlnis no longer a synonym forconsole.logand now prints through*print-fn*like CLJS - Add
double?,vary-meta,symbolcore fns - Add
with-out-str - Add
print,pr - Fix:
coll?returnedtruefor functions. Useaset,agetfor raw property access on non-objects. - Make
core.jsmore suitable for treeshaking when only a few functions from it are used. pr-strandprnno 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:defaultlike CLJS
- Fix
(vec (list ..))edge case - Improve inference of collections, such that
(let [x {:a 1}] (x :a))works - Support
.indexOfon lazy seqs, matching CLJS
- Replicant support. See example.
- Support
:depsinsquint.edn, resolved viaclojure -Spath, added to:pathsimplicitly. Squint only supports:git/shaand:local/rootlibraries 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"]))istruepersistent!no longer freezes its argument, so persistent structures stay extensible for symbol-keyed metadatavswap!andvreset!return the new value, like Clojurenthon an out-of-bounds index without a default now throws, like Clojuredisjon nil returns nil instead of throwingnamenow returns the part after the/for a namespaced keyword/symbol (e.g.(name :foo/bar)->"bar"), consistent withnamespaceso they round-trip. Since keywords are strings in squint this also applies to slash-containing strings (differs from Clojure stringname).namespaceuses the same/threshold asname, 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 earmuffeddef(e.g.*foo*) compiles to a mutable box{value ...}; references read.value,set!assigns it, andbindingsaves/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-metadataoption; protocol methods fall back to an impl on the receiver's metadata keyed by the fully-qualified method name:require-macrosaccepts a bare symbol libspec (not only a vector)- Macros in a
.cljc/.cljsnamespace required via an:asalias (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) andunchecked-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
=distinguishingnullfromundefined; both arenilin CLJS, so(= js/undefined nil)and e.g.(= (keys nil) nil)now returntrue. - Apply reader metadata (
^:foo) on vector, map, set andfnliterals 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 returntrue, matching CLJS. Equal-typed collections keep their existing fast paths. - Fix named variadic
fnwhose name munges (e.g.dispatch!) emitting an invalid self-reference (dispatch!.cljs$...) in its dispatcher; the munged name is now used. - Fix
def/defnwhose name shadows a:requirealias or:referproducing 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 barefoois the var,foo/barstays the alias. - Add
clojure.walk(walk,prewalk,postwalk,prewalk-replace,postwalk-replace,keywordize-keys,stringify-keys, and the*-demohelpers) empty,conj,assoc,intoand othercopy-based operations now carry metadata, matching Clojure (previously metadata was dropped on the freshly built structure);with-meta/copynow also support lists#htmlnow escapes literal string attributes#htmlnow does not emittruefor a boolean-true attribute, but emits bare attribute#htmlnow gates CSS output onstyleattribute name- CLI: shell tab completion via babashka.cli's hidden
org.babashka.cli/completionscommand. 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'sdispatch(standardUsage/Commands/Optionshelp, errors to stderr). Builds on #691 (@lread)
- Fix #832: nREPL server hung on advertised ops.
info/eldoc/lookup,complete(includingjs/interop completion) andload-fileare now implemented. - Fix
parse-longreturning out-of-range values instead ofnil(the safe-integer upper bound was a no-op due to a chained comparison) - Fix
select-keysdropping keys mapped tonil(loose!= undefinedmatchednull); nil-valued keys are now kept, matching Clojure - Fix
clojure.string/splitlimit 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 JSString.split; limit0discards trailing empties, negative keeps them - Fix
comparethrowing on booleans;(compare false true)->-1and(sort [true false])no longer throws, matching CLJS clojure.set/intersectionandunionnow 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?returningfalsefor maps;(seqable? {:a 1})->true, matching CLJS (seqalready worked on objects) - Fix
nthreturning the not-found default for an in-bounds element that isundefined(e.g. sparse /object-array/ JS-interop arrays); it now decides found-ness by the index bound, not the value - Fix
parse-doublenot 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/prnnow printInfinity,-InfinityandNaNas##Inf,##-Infand##NaN, matching CLJS (stris unchanged)
- Add support for Vite 5-8
- 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).
- Browser nREPL support. See docs
- Fix #815:
strwrapping known-numeric infix expressions in??'', which esbuild flagged assuspicious-nullish-coalescing. (@willcohen) - Fix #820:
:macrosoption silently ignored when passed tocompileString/compileStringExfrom JavaScript callers (string keys were keyword-ized byclj-ize-optsand no longer matched the symbol-keyed macro lookups incompile*). (@willcohen)
- #809: add
squint.compiler/compile*andsquint.compiler/transpile*which accept either a string or a sequence of pre-parsed forms, skipping theforms -> string -> formsroundtrip for SSR use cases. The previous namescompile-string*/transpile-string*are retained as deprecated aliases. - Fix #810: shorthand classes in
#html/#jsxwere erased when an attrs map was present without a:classkey (e.g.[:div.myclass {}]).
-
Add multimethod support (#806):
defmulti,defmethod,get-method,methods,remove-method,remove-all-methods,prefer-method,prefers, and hierarchy opsisa?,derive,underive,make-hierarchy,parents,ancestors,descendants. -
cljs.test/reportis now a multimethod, extensible viadefmethod:(defmethod report [:cljs.test/default :begin-test-var] [m] ...)test-varnow fires:begin-test-var/:end-test-varevents.
- Accept plain
awaitin async functions, in anticipation of CLJS next. The legacyjs-awaitandjs/awaitforms continue to work as aliases for now and may be deprecated in a future version. - Add built-in
cljs.test/clojure.testsupport:deftest,is,testing,are,use-fixtures,async,run-tests. - Fix
with-metanow preserves callability when applied to a function - Fix #783: auto-load macros from
.cljcfiles 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-nsfor cherry namespace resolution
- Fix #799: forgot to add
squint.mathfile topackage.json
- Fix emitting negative zero value (
-0.0) - Add
squint.math, also available asclojure.mathnamespace (a direct port of the original)
- #779: Added
compare-and-swap!,swap-vals!andreset-vals!(@tonsky) - #788: Fixed compilation of
dotimeswith_binding (@tonsky) - #790: Fixed
shufflenot working on lazy sequences (@tonsky) - Multiple
:require-macroswith:refernow accumulate instead of overwriting (@willcohen)
- 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
letoverdefnto capture values.
- Fix
js-yieldandjs-yield*in expression position - Implement
some?as macro
- Fix #758:
volatile!,vswap!,vreset! pr-str,prnetc now print EDN (with the idea that you can paste it back into your program)- new
#js/Mapreader that reads a JavaScriptMapfrom a Clojure map (maps are printed like this withpr-strtoo)
- Support passing keyword to
mapv - #759:
doseqcan't be used in expression context - Fix #753: optimize output of dotimes
alengthas macro
- Inline
identical?calls - Clean up emissiong of paren wrapping
- Add
nat-int?,neg-int?,pos-int?(@eNotchy) - Add
rand
- Fix rendering of
nullandundefinedin#html
- #747:
#htmlescape fix
- Optimize nested
assoccalls, e.g. produced with-> - Avoid object spread when object isn't shared (
auto-transient)
- Optimize
streven more
Remove debug output from compilation
- Optimize
=,and, andnot=even more
not=on undefined and false should returntrue
- Optimize code produced for
assoc,assoc!andgetwhen object argument can be inferred or is type hinted with^object - Optimize
strusing macro that compiles into template strings +?? ''for null/undefined - Fix #732:
take-lastshould returnnilor empty seq for negative numbers
- #725:
keysandvalsshould work onjs/Map
- Make
map-indexedandkeep-indexedlazy
- Compile time optimization for
=when using it on numbers, strings or keyword literals
Cljdoc chose squint for its small bundle sizes and easy migration off of TypeScript towards CLJS
- Switch
=to a deep-equals implementation that works on primitives, objects,Arrays,MapsandSets
- Fix #710: add
parse-double - Fix #714:
assoc-inonnilorundefined - Fix #714:
dissoconnilorundefined
- Basic
:import-mapssupport insquint.edn(just literal replacements, prefixes not supported yet)
- Fix #704:
whiledidn't compile correctly - Add
clojure.string/includes? - Emit less code for varargs functions
- Fix solidJS example
- Documentation improvements (@lread)
- Fix #697:
ClassCastExceptionin statement function when passed Code records
- Fix #680: support import attributes using
:withoption in require, e.g.:with {:type :json}
- Implement
not=as function - Fix #684: JSX output
- #678: Implement
random-uuid(@rafaeldelboni) - Fix #681: support unsafe HTML via
[:$ ...]tag
- #671: Implement
trampoline(@rafaeldelboni) - Fix #673: remove experimental atom as promise option since it causes unexpected behavior
- Fix #672: alias may contain dots
- Fix #669: munge refer-ed + renamed var
- Fix #661: support
throwin 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
- #653: respect
:context exprincompile-string - #657: respect
:context exprinset!expression - #659: fix invalid code produced for REPL mode with respect to
return
- #651 Support
:require+:rename+ allow renamed value to be used in other :require clause
- Fix #649: reset ns when compiling file and fix initial global object
- Fix #647: emit explicit
nullwhen written in else branch ofif
- Fix #640: don't emit anonymous function if it is a statement (@jonasseglare)
- Fix #643: Support lexicographic compare of arrays (@jonasseglare)
- Fix #602: support hiccup-style shorthand for id and class attributes in
#jsxand#html
defclass: elide constructor when not provided
- Fix #603: don't emit multiple returns
- Drop constructor requirement for
defclass
- Fix #626: Implement
take-last - Fix #615:
(zero? "0")should returnfalse - Fix #617:
deftypefield name munging problem - Fix #618: Named multi-arity
fnargs don't get munged (@grayrest) - Fix #622: operator precendence issue with
|andif - Add
clojure.stringfunctionslower-case,upper-case,capitalize(@plexus)
- Fix #609: make
removereturn a transducer when no collection is provided - Fix #611: Implement the
set?function (@jonasseglare) - Fix #613: Optimize
aset
- Fix #605: merge command line
--pathswithsquint.ednconfig properly - Fix #607: make
mapcatreturn a transducer if no collections are provided (@jonasseglare)
- Fix #255: fn literal with rest args
- #596: fix unary division to produce reciprocal
- #592: fix
clj->jsto not process custom classes
- #585: fix
clj->jsto realize lazy seqs into arrays
- #586: support extending protocol to
nil
- Fix #572: prevent vite page reload
- Fix watcher and compiler not overriding
squint.ednconfigurations with command line options, take 2
- Fix watcher and compiler not overriding
squint.ednconfigurations with command line options.
- Fix watcher not being called
- Allow passing
--extensionand--pathsvia CLI
- Fix #563: prioritize refer over core built-in
- Update
chokidarto v4 which reduces the number of dependencies
- BREAKING: Dynamic CSS in
#htmlmust now be explicitly passed as map literal:(let [m {:color :green}] #html [:div {:style {:& m}}]). Fixes issue when usinglit-htmlin combination withclassMap. See demo
- #556: fix referring to var in other namespace via global object in REPL mode
- Pass
--replopts towatchsubcommand in CLI
- #552: fix REPL output with hyphen in ns name
- #542: fix
runon Windows
- #536: HTML is not escaped in dynamic expression
- #537: Fix
not: wrap argument in parens - Return interop expression in function body
- Prefer value from props map over explicit value
#htmlimprovements, support:&for spreading props
- #517: Preserve state over REPL evals
- #513: Fix
shufflecore function random distribution and performances - #517: Fix re-definition of class with
defclassin REPL - #522: fix
nil#htmlrendering issue
- #509: Optimization: use arrow fn for implicit IIFE when possible
- Optimization: emit
constin let expressions, which esbuild optimizes better
- Don't wrap arrow function in parens, see this issue
- Fix #499: add support for emitting arrow functions with
^:=>metadata
- Fix #505: Support
:renamein:require
- Fix #490: render css maps in html mode
- Fix #502: allow method names in
defclassto override squint built-ins
- Fix #496: don't wrap strings in another set of quotes
- Fix rendering of attribute expressions in HTML (should be wrapped in quotes)
- Compile destructured function args to JS destructuring when annotated with
^:js. This benefits working with vitest and playwright.
- #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.
- Add new
#htmlreader for producing HTML literals using hiccup. See docs and playground example. - #483: Fix operator precedence problem
- Add
simple-benchmark
- #468: Keywords in JSX should render with hyphens
- #466: Fix
doseqexpression withset!in function return position
- #458: don't emit
nullin statement position
- #455: don't export non-public vars
- Fix infix operator in return position
- Allow playground to use JSX in non-REPL mode
- Add transducer arity to all existing core functions
- Support
^:gen+js-yield+js-yield*to write JS generator functions. See playground - Add
update-keysandupdate-vals - Add
=as reified function
- #449: fix issue with
:refer
- Add
memoize,filtertransducer arity,peek,pop - Export classes defined with
defclass - Support
^:asyncObject method indefclass
- Better support for pragmas and JSDoc via
js*+//and/* */ - Add
rem,nnext,str/end-with?,str/index-ofandstr/last-index-of - Fix alias with hypen in REPL mode
- Keep top level strings and comments (via
js*) before imports (for JSDoc, Next.js"use client", etc)
- Fix
compileStringin JS API
- Optimization: sort largest set first for
set/union, and smallest first forset/intersection - Add
sorted-set,long,abs,keep-indexedtransducer arity
- The
childrenfunction intree-seqmay returnnil
- Add
clojure.set/join - Add
tree-seq,flatten,seq?andsequential?
- Add
clojure.setfunctionsselect,rename-keys,rename,project, andmap-invert(@PEZ) - Fix
reduce-kvwithjs/Mapinput
- Add more
clojure.setfunctions:difference,union,subset?, andsuperset?(@PEZ)
- Let any object that has
Symbol.iterablebe destructureable even if it is notinstance of Object
- Initial version of
clojure.set - #418: Add
reductions - Add
bit-shift-leftand morebit-related macros - Fix
notwith respect to truthiness - Fix
reducewithout initial value + empty coll, it should callf() - Add serve-playground bb task
- Update playground with button for creating a blank AOC playground
- #407: fix conditional rendering
- Add
not-empty - Fix
into+ set + xform
- More helpful error from JS when using unresolved symbol in REPL mode
- Allow
>,<etc to be used as HOFs - Fix
str/splitwith respect to trailing empty split elements
- Fix vararg functions in REPL mode
- #394: add
int - #393:
Mathcan be used withoutjs/prefix - Expose compiler state via
compileStringExfor playground, preserves namespace transitions
- Restore backward compatibility with code that is compiled with older versions of squint
- Optimize various outputs for smaller size
- Add
js-in
- Support
into+xform
- Support
sorton strings
- #386: allow expression in value position in map literal
- Improvements with respect to laziness in
mapcatandconcat - Do not array mutate argument in
reverse
- Escape JSX attribute vector value (and more)
map+transducesupport- Fix
forin 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)
- Add
js-modandquot
- #380: Don't emit space in between
#jsxtags - Add
re-find
- Add
condpmacro
- Use
compareas default compare function insort(which fixes numerical sorting)
- Allow
assoc!to be called on arbitrary classes (regression)
- Improve
getto callgetmethod when present.
- False alarm, I was playing the pinball game in low power mode on my mobile 🤦
- Revert truthiness checks via funcall, negative impact on performance with pinball game on mobile
- Allow keywords and collections to be used as functions in HOFs
- Make filter, etc aware of truthiness
- Reduce code size for truthiness checks
- Add
str/split-lines - Add
partition-by - Add
parse-long - Add
sort-by
- Fix top level await
- Support multiple dimensions in
aset - Add
coercive-=as alias for== - Add
js-delete
- Fix
min-keyandmax-keyand improve tests
- Add
min-keyandmax-key - Fix
defoncein REPL-mode
- Fix
doseqandforwhen binding name clashes with core var
- No-op release to hopefully fix caching issue with jspm
- Several REPL improvements
- Improve https://squint-cljs.github.io/squint/
- Allow alias name to be used as object in REPL mode
- Copy resources when using
squint compileorsquint watch
- Return map when
select-keysis called withnil - nREPL server: print values through
cljs.pprint(@PEZ)
- Initial (incomplete!) nREPL server on Node.js:
npx squint nrepl-server :port 1888 - Update/refactor threejs example
- #360:
assoc-in!should not mutate objects in the middle if they already exist - Evaluate
lazy-seqbody just once - Avoid stackoverflow with
minandmax - #360: fix assoc-in! with immutable objects in the middle
- Add
mod,object? - Optimize
get - Add threejs example
- #357: fix version in help text
- Fix iterating over objects
- Add
clojure.string'striml,trimr,replace - Fix
examples/vite-reactby addingpublic/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
- #347: Add
:preand:postsupport infn - Add
number? - Support
docstringindef
- Handle multipe source
:pathsin a more robust fashion
- #344: macros can't be used via aliases
- Add
squint.ednsupport, see docs - Add
watchsubcommand to watch:pathsfromsquint.edn - Make generated
letvariable 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
- Add
bit-andandbit-or
- Include
lib/squint.core.umd.jswhich defines a globalsquint.coreobject (easy to use in browsers, see docs)
- Add
subs,fn?,re-seq - Add
squint.ednwith:pathsto resolve macros from (via:require-macros)
- Fix
andandorwith respect to CLJS truthiness
- Respect CLJS truth semantics: only
null,undefinedandfalseare non-truthy,0and""are truthy. - Fix
dotimes
squint replimprovements
- Do not resolve binding in
catchto core var - Fix reading
.cljcfiles - Allow passing JS object as opts in JavaScript API's
compileString
- Fix
instance?in return position to-array,str/starts-with?
- Support next on non-arrays
- Add
compare
- Fix
into-array
- Add
into-array,some-fn,keep-indexed - Fix for
lazy-seqwhen body returnsnil
- Add
max,min,every-pred
- Add
reduce-kv
- #320: fix overriding core vars
- Add
rand-nth,aclone,add-watch,remove-watch
- #288: support
defclass. See doc/defclass.md. - #312: implement doall and dorun
- Drop cherry core from NPM package (cruft from porting cherry to squint)
- Fix compilation of empty list
- Fix
andandorwithout arguments - #308:
doseqin return position emits invalid code
- Add
js-obj
- Add
foranddoseq(@lilactown)
- #289: support
:asalias with hyphen in namespace require libspec
- #286: make dissoc work with multiple keys
- #284: fix undefined keys/values when passing objects and maps to conj
- #274: fix logic precedence by wrapping in parens
Add preliminary Node.js API in node.js
- Support
{:& more :foo :bar}syntax in JSX to spread the more map into the props, inspired by helix
- Add
zero?pos?andneg?core functions
- Fix
booleancore function export
- Escape boolean in JSX attribute
- Add
booleancore function
- Fix
+symbol import by bumping shadow-cljs - Move
@babel/preset-reactdependency to dev dependency
- Fix async/await + variadiac arguments
- Fix namespaced component in JSX
- Change default extension back to
.mjs. Use--extension jsto change this to.js.
- Fix rendering of number attributes in JSX
- Support
--extensionoption to set extension for JS files - Change default extension from
.mjsto.js