Repository navigation
This is a big release that officially remove the experimental qualifier to the Rhai Grain transpiler and VM.
A new feature, no_ast is added to completely remove the AST, parser, tokenizer and optimizer from the build. Such a build can only run Rhai Grain bytecodes; it cannot parse Rhai script text.
Lazy-loading is now also supported natively in all modes. Lazy-loaded modules only look up functions when they're being called, thus substantially cutting down runtime footprint.
There are a large number of bug fixes as well, in addition to some performance improvements.
Bug fixes
- (Fuzzing) Fixed missing data-race condition in native function callbacks (
#1161). - Errors raised during built-in binary operations (such as
100 / 0) now contain properPositioninformation (identified by Rhai Grain ). - Number of operations reported to
Engine::on_progressnow properly count scripted function calls from native Rust functions (identified by Rhai Grain). Previously all operation counts performed by a scripted function callback (including a closure) from a native Rust function are discarded. - Capturing the caller's scope via
call!(fnptr, args...)now works properly in Rhai Grain. .shared()method calls now work property in Rhai Grain.- Missing capabilities in scripts related to some constants (especially in
switchcases, arrays and object maps) now work properly in Rhai Grain (thanks@yinho999#1182). - Failed function resolutions are now cached properly for calls with other than two arguments - a regression from version 1.10 (thanks
@ImTheSquid#1183). - A function resolution cache is now created (if none exists) when entering a block. Previously, a loop body evaluated with no cache yet would resolve every function call again on each iteration (thanks
@ImTheSquid#1183). - Assigning a constant into a container variable (array, map etc.) now works properly without making the value read-only (thanks
@cuervolu#1187). - Under
sync, a method call on a shared variable with a closure argument that captures the same variable now raisesErrorDataRace, as it does withoutsync, instead of panicking while resolving the function.Dynamic::is_lockednow returnstrueundersyncwhen the value cannot be read, which includes being locked for write by the current thread (thanks@yuvalrakavy#1190). - A panic inside a native Rust function that takes its first argument by value, called with a variable first argument, now unwinds normally and can be caught by
catch_unwind. Previously the copied first argument was restored only on the normal-return path, so the unwind tripped an internal assertion and the process aborted (thanks@yuvalrakavy#1189).
Rhai Grain is now at feature parity with the AST interpreter
- Rhai Grain is no longer experimental.
- New
no_astfeature added that excludes theAST, its interpreter, the tokenizer, parser and optimizer for a minimized build (#1160). Under this feature flag, the Rhai Grain VM is the only venue to evaluate a script. - Bare function names are now supported as variables in Rhai Grain (
#1158). - Custom syntax that does not modify the
scopeis now fully supported in Rhai Grain (#1173). Custom syntax that modifies thescoperemains non-lowerable fragments. - Importing modules, the
global::namespace, theexportandimportstatements are all supported by Rhai Grain (#1179). - The
Engine::on_map_missing_propertycallback now works with Rhai Grain (#1164). - The
Engine::on_def_varcallback now works with Rhai Grain (#1170). However, the nesting level reported byVarDefInfois always zero, since all nesting information is lost once theASTis lowered to bytecodes. .call(fnptr, args...)and.curry(...)method calls now work in any position (instead of only on a chain's root) in Rhai Grain.- Rhai Grain bytecodes transpilation is optimized (thanks
@ImTheSquid#1156). - Rhai Grain VM is now at par or faster than the AST interpreter for scripts index assignments (
#1163). - Rhai Grain VM is now at par or faster than the AST interpreter for scripts with callbacks (
#1159). - Rhai Grain VM is now 1.8-2x faster than the AST interpreter when running
switchstatements (#1162,#1165). - Rhai Grain VM is now 2x faster than the AST interpreter when running
!<bool>expressions. rhai-runnow supports loading and executing Rhai Grain bytecode files if thegrainfeature is enabled (#1160).- The example
grain_dumpis now split into two CLI tools inbin:grain-compile, which compiles a Rhai script into Rhai Grain bytecodes, andgrain-dumpwhich dissembles a Rhai Grain bytecodes files (#1160). grain-dumpnow disassembles Rhai Grain bytecodes files with more complete information (#1168).
Lazy loading of plugin module functions
- Contributed by
@ImTheSquid#1178. - Functions in plugin modules can now be resolved lazily: a
Modulecan hold static manifests of plugin modules (generated via#[export_module(manifest)]andexported_manifest!) alongside its normal functions, and functions in manifests are not registered but looked up only when called. - Lazy-loading is opt-in.
- Every package defined via
def_package!now has anew_lazyconstructor that keeps the functions of plugin modules within their manifests, looking them up only when called. For example,Engine::new_raw()withStandardPackage::new_lazy()uses about 16x less heap thanEngine::new(), and builds the standard library about 8x faster, at the cost of slower function resolution the first time a function is called. - Lazy-load plugin's are supported by both the
ASTinterpreter and Rhai Grain. - Use the new
Module::from_manifest(the lazyexported_module!) orModule::combine_manifest(the lazycombine_with_exported_module!) API to create a lazy-loaded module or add the manifest of lazy-loaded functions to a module. Module::register_lazy_functionsregisters all lazy-loaded functions up-front instead, for the same speed as before.
Feature flag to replace smartstring with compact_str
- Contributed by
@hoppworks#1175. - A new
compact_strfeature that usescompact_strinstead ofsmartstringfor identifiers and object map keys smartstringis archived and unmaintained (RUSTSEC-2026-0249) and licensed underMPL-2.0+(#897), whilecompact_stris licensed under the more permissiveMIT.- Under
compact_str, the key type ofMap(andIdentifierunderinternals) isCompactStringinstead ofSmartString. - Under
compact_str,serde-serializable types useCompactStringdirectly instead ofStringsince theserdefeature ofcompact_strisno-std-safe, unlike that ofsmartstring. compact_stris intended to become the default in version 2.0.
Enhancements
- Added
AGENTS.mdfiles and a language reference cheat-sheet for AI (RHAI_CHEATSHEET.md). - String interpolation now resolves
to_stringwith the evaluation's function resolution caches, instead of creating a newNativeCallContext(which cloned the global runtime state) for each interpolated value (thanks@ImTheSquid#1183).