0.12.0
On this page
Released 2026-10-22. GitHub release | Downloads
Added
- HTML Encoding: Added
encodeForHTML()and itshtmlEditFormat()alias, matching BoxLang JVM output. - SQLite Datasources: Register SQLite databases programmatically or through minimal
matchbox.tomldatasource configuration. - Inline CLI Execution: Execute source with
--evalor-e, including prelude functions and source-located diagnostics.
Changed
dateFormat,timeFormatanddateTimeFormatnow mirror BoxLang'sDateTimeFormatBIF: masks are JavaDateTimeFormatterpatterns (case sensitive,mmis minutes,MMis month, invalid letters and repeat counts raise Java's errors), with Java's default masks, named masks (short,medium,long,full,iso,iso8601,odbc,javascript,epoch,epochms),timezoneandlocalearguments and English, German, Spanish, French, Italian, Portuguese, Dutch, Russian, Japanese and Chinese locale text. Locales without bundled data fall back toen_US; named regions other than UTC/GMT use MatchBox's fixed-offset zone table (no tz database).createDateTimeandcreateDateaccept every argument as optional, like BoxLang (createDateTime( 2024, 3, 5, 14, 7, 9 )works, no arguments returns now).
Fixed
- WASM time traps: The VM scheduler and
getTickCount()now useweb_timeclocks; synchronous scheduler waits poll instead of calling unsupportedstd::thread::sleepin WASM builds. <bx:switch>evaluates itsexpression, runs only the matching<bx:case>(no fall-through,valuewithdelimitersmatches any listed item) and<bx:defaultcase>only when nothing matches; text after the switch is kept (#93).super.method( args )works in class methods: it calls the parent class implementation withthisbound to the current instance, across any depth of inheritance and inside closures. Named arguments are not supported withsuper.new Child()callsinit()inherited from a parent class whenChilddefines none (the compiler only looked at the class itself).--target wasiworks again: the WASI runner stub lost its embed region in an earlier refactor, so packaging always failed with "WASI stub is missing the BOXLANG_EMBED sentinel".--target wasmproduced an invalid module (a custom section written without its header) that no runtime could load; it is now the same as--target wasi. The docs said--target wasmwas browser oriented; use--target jsfor the browser.- Native Fusion reads
native/Cargo.toml: its[dependencies]are added to the generated build (relativepathdependencies are resolved againstnative/), as the Native Fusion guide already described. Redeclaring a crate the build provides (matchbox_vm,postcard,bincode,anyhow) is an error. - Java interop (
bif-jni): methods and constructors are chosen by their parameter types, not just argument count (sb.append( 2 ),String.valueOf( 5 )), static methods work oncreateObject( "java", ... )references (Math.max( 1, 2 ),Integer.parseInt( "42" )), and Java exceptions report their class and message. for ( row in query )iterates the rows of a query (it failed with "Iteration only supported for arrays and structs"). A BIF that is compiled out now says which build feature provides it, and the QoQ error names theqoqfeature.- Member functions that map to existing BIFs now resolve: struct
keyArray,keyList,valueArray,filter,map,reduce,some,every,none,delete,insert,update,clear,copy,sort,findValue,hash; stringlistToArray,listPrepend,listInsertAt,listSetAt,listReduce,jsonDeserialize,toBase64,toBinary,yesNoFormatand other list/string members; arrayjoin,findNoCase,isDefined; numbermax,min,formatBaseN; datehash; futureisDone. - Script
lock name="x" timeout=n { ... }blocks parse and run their body (a lock never contends in the single-threaded VM). Scriptthread { ... }now parses and reports "The thread component is not supported yet in MatchBox" instead of a struct-literal parse error. - Labeled loops:
outer: for ( ... )withcontinue outer/break outer(alsowhileanddo) now work like BoxLang. Labels were parsed and silently ignored, socontinue outeronly continued the inner loop. - The
modoperator (7 mod 3) and unarynot(not x) now parse, like BoxLang.modstays usable as an identifier. privateclass methods are enforced: calling one from outside the class (or an unrelated class) throws, while calls from the class, its subclasses and its closures keep working.- Class properties generate
getX()/setX()by default (accessors=falseopts out), generated setters return the instance so calls chain, andobj.name/obj.name = vuse the accessors when there is no such field, as in BoxLang. <bx:include template="...">includes the named template instead of an empty path (#93).class extends=Base implements=Speaker(andextends:Base) accept an unquoted class name like BoxLang; only the quoted form parsed before.- Script-level
variablesis now the same store as bare variables (variables.k = 1; kandj = 2; variables.jwork), and CLI scripts and class methods have arequestscope. - CLI argument handling now follows BoxLang's
BoxRunnerandCLIGetArgs: options only count before the script file, everything after it goes to the script (matchbox app.bxs -vruns the script with-v),-h/--help/-v/--versionare global only as the sole argument, unknown options fall through like BoxLang, andcliGetArgs()parses--opt=value,--!opt/--no-opt,-o=value,-abcand quoted values exactly like BoxLang (a value is never taken from the next token) and keeps the first script argument. Breaking: put MatchBox options before the file (matchbox --target esp32 --chip esp32s3 --flash app.bxs); the documentation is updated, and the old--separator is no longer special. Adds BoxLang's runtime flags:--bx-debug,--bx-code <code>,--bx-printAST(file,--bx-codeor stdin) are implemented,--bx-config/--bx-homeare accepted (never reach the script) with a warning that MatchBox ignores them,--bx-transpileis rejected clearly; and theserver.cliscope (args,parsed,executionPath,command) withserver.boxlang.cliMode. <bx:loop>works:from/to/step/indexcounting loops,array,list,collectionandconditionloops no longer run forever or printnull(#93).- Security: ESP32 firmware no longer ships default Wi-Fi credentials. Without
MATCHBOX_ESP32_WIFI_SSID/MATCHBOX_ESP32_WIFI_PASSWORDat build time Wi-Fi stays off and the boot log says so (the credentials that were in the source should be considered public). - Destructuring rest elements (
[ a, ...rest ] = arr,{ a, ...others } = struct) are now assigned instead of silently dropped. arraySlicenow follows BoxLang:startdefaults to 1,lengthis a count (0 or omitted means to the end, negative trims from the end) and a negativestartcounts from the end.- Calling a function without a
requiredargument now throwsRequired argument [a] is missing for function [f](typeApplication) like BoxLang, instead of silently passing null. - Tree-shaking no longer drops prelude functions that are only reached through member calls (
[3,1,2].sort(),.first(),.reverse(),.sum(), ... failed with "BIF arraysort not found" outside--no-shaking). - Removed prelude copies of
abs,min,max,arrayIsEmpty,arrayPrepend,arrayContainsandarrayContainsNoCasethat shadowed the native BIFs depending on tree-shaking;arrayPrependnow returns the array andarrayContainsis case-sensitive for arrays and case-aware for sets. - Closures at script level can now see the
for ( n in ... )loop variable (and index) instead of failing with "Variable 'n' not found"; assignments to the loop variable in the body are shared with closures. future.get()inside a native callback (map,filter, ...) no longer hangs: the nested callback now lets other fibers run while it waits.- Array members
map,each,filter,reduce,some,everyandnoneno longer use the Set helpers:mapkept only unique results, and callbacks now receive(value, index, array)((accumulator, value, index, array)forreduce) like BoxLang. variables.n++/++variables.ninside classes and scripts no longer fail with "Fused increment only supported on structs and instances", and prefix++/--now accept member targets such as++s.n.new C()now evaluates to the instance wheninit()returns nothing ornull, and to the returned value otherwise, matching BoxLang.- Tree-shaking no longer drops prelude functions that are only reached through member calls (
[3,1,2].sort(),.first(),.reverse(),.sum(), ... failed with "BIF arraysort not found" outside--no-shaking). - Removed prelude copies of
abs,min,max,arrayIsEmpty,arrayPrepend,arrayContainsandarrayContainsNoCasethat shadowed the native BIFs depending on tree-shaking;arrayPrependnow returns the array andarrayContainsis case-sensitive for arrays and case-aware for sets. - Corrected the native fusion documentation example that used the nonexistent
BxValue::new_string; strings are returned withBxValue::new_ptr( vm.string_new( text ) ).
Documentation
- Documented which BIF groups exist in WASM builds:
hash()needs thebif-cryptofeature,http()is not usable in the browser.