Compare commits
16 Commits
982b972d3b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 939048418b | |||
| 2fe191f2a3 | |||
| b1a5f47b05 | |||
| 013075bc82 | |||
| 9f0bb3e693 | |||
|
|
ca18cdd7f4 | ||
|
|
2474c1fec1 | ||
|
|
541844e1e1 | ||
|
|
172bc14996 | ||
|
|
4627fb22a5 | ||
|
|
1326ab933c | ||
|
|
03b1a1cea2 | ||
|
|
ee64fd90aa | ||
|
|
fd162ab99f | ||
|
|
1728de7dcd | ||
|
|
d12b124f67 |
2
.github/workflows/benchmark.yml
vendored
2
.github/workflows/benchmark.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
name: Run Rust benchmark
|
name: Run Rust benchmark
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v6
|
||||||
- run: rustup toolchain update nightly && rustup default nightly
|
- run: rustup toolchain update nightly && rustup default nightly
|
||||||
- name: Run benchmark
|
- name: Run benchmark
|
||||||
run: cargo +nightly bench --features decimal,metadata,serde,debugging | tee output.txt
|
run: cargo +nightly bench --features decimal,metadata,serde,debugging | tee output.txt
|
||||||
|
|||||||
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@@ -14,8 +14,8 @@ jobs:
|
|||||||
msrv:
|
msrv:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/cache@v1
|
- uses: actions/cache@v5
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/bin
|
~/.cargo/bin
|
||||||
@@ -76,7 +76,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
- name: Setup Toolchain
|
- name: Setup Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -101,7 +101,7 @@ jobs:
|
|||||||
#- {os: macos-latest, flags: "--profile macos", experimental: false}
|
#- {os: macos-latest, flags: "--profile macos", experimental: false}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
- name: Setup Toolchain
|
- name: Setup Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -128,7 +128,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
- name: Setup Generic Wasm Toolchain
|
- name: Setup Generic Wasm Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -153,7 +153,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
- name: Setup Toolchain
|
- name: Setup Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -182,7 +182,7 @@ jobs:
|
|||||||
- {toolchain: stable, os: windows-latest, experimental: false, flags: "--features metadata"}
|
- {toolchain: stable, os: windows-latest, experimental: false, flags: "--features metadata"}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
- name: Setup Toolchain
|
- name: Setup Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
feature_powerset:
|
feature_powerset:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@v1
|
- uses: dtolnay/rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|||||||
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,6 +1,24 @@
|
|||||||
Rhai Release Notes
|
Rhai Release Notes
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
Version 1.16.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Fixes a panic when using `this` as the first parameter in a namespace-qualified function call.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.15.1
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* `Dynamic::deep_scan` is fixed so now it properly scans arrays, object maps and function pointers embedded inside data.
|
||||||
|
|
||||||
|
|
||||||
Version 1.15.0
|
Version 1.15.0
|
||||||
==============
|
==============
|
||||||
|
|
||||||
@@ -14,6 +32,7 @@ Enhancements
|
|||||||
|
|
||||||
* Expressions involving `this` should now run slightly faster due to a dedicated `AST` node `ThisPtr`.
|
* Expressions involving `this` should now run slightly faster due to a dedicated `AST` node `ThisPtr`.
|
||||||
* A `take` function is added to the standard library to take ownership of any data (replacing with `()`) in order to avoid cloning.
|
* A `take` function is added to the standard library to take ownership of any data (replacing with `()`) in order to avoid cloning.
|
||||||
|
* `Dynamic::take` is added to take ownership of the data (replacing with `()`) in order to avoid cloning.
|
||||||
* `EvalAltResult::ErrorMismatchOutputType` now gives a better name for the requested generic type (e.g. `&str` is now `&str` and not `string`).
|
* `EvalAltResult::ErrorMismatchOutputType` now gives a better name for the requested generic type (e.g. `&str` is now `&str` and not `string`).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
Cargo.toml
10
Cargo.toml
@@ -3,7 +3,7 @@ members = [".", "codegen"]
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "rhai"
|
name = "rhai"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
rust-version = "1.61.0"
|
rust-version = "1.61.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
@@ -21,20 +21,20 @@ categories = ["no-std", "embedded", "wasm", "parser-implementations"]
|
|||||||
smallvec = { version = "1.7", default-features = false, features = ["union", "const_new", "const_generics"] }
|
smallvec = { version = "1.7", default-features = false, features = ["union", "const_new", "const_generics"] }
|
||||||
ahash = { version = "0.8.2", default-features = false, features = ["compile-time-rng"] }
|
ahash = { version = "0.8.2", default-features = false, features = ["compile-time-rng"] }
|
||||||
num-traits = { version = "0.2", default-features = false }
|
num-traits = { version = "0.2", default-features = false }
|
||||||
bitflags = { version = "1", default-features = false }
|
bitflags = { version = "2", default-features = false }
|
||||||
smartstring = { version = "1", default-features = false }
|
smartstring = { version = "1", default-features = false }
|
||||||
rhai_codegen = { version = "1.5.0", path = "codegen", default-features = false }
|
rhai_codegen = { version = "1.5.0", path = "codegen", default-features = false }
|
||||||
|
|
||||||
no-std-compat = { git = "https://gitlab.com/jD91mZM2/no-std-compat", version = "0.4.1", default-features = false, features = ["alloc"], optional = true }
|
no-std-compat = { git = "https://gitlab.com/jD91mZM2/no-std-compat", version = "0.4.1", default-features = false, features = ["alloc"], optional = true }
|
||||||
libm = { version = "0.2", default-features = false, optional = true }
|
libm = { version = "0.2", default-features = false, optional = true }
|
||||||
hashbrown = { version = "0.13", optional = true }
|
hashbrown = { version = "0.16", optional = true }
|
||||||
core-error = { version = "0.0", default-features = false, features = ["alloc"], optional = true }
|
core-error = { version = "0.0", default-features = false, features = ["alloc"], optional = true }
|
||||||
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true }
|
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true }
|
||||||
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
|
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
|
||||||
unicode-xid = { version = "0.2", default-features = false, optional = true }
|
unicode-xid = { version = "0.2", default-features = false, optional = true }
|
||||||
rust_decimal = { version = "1.16", default-features = false, features = ["maths"], optional = true }
|
rust_decimal = { version = "1.16", default-features = false, features = ["maths"], optional = true }
|
||||||
getrandom = { version = "0.2", optional = true }
|
getrandom = { version = "0.3", optional = true }
|
||||||
rustyline = { version = "11", optional = true }
|
rustyline = { version = "17", optional = true }
|
||||||
document-features = { version = "0.2", optional = true }
|
document-features = { version = "0.2", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ metadata = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
syn = { version = "1.0", features = ["full", "parsing", "printing", "proc-macro", "extra-traits"] }
|
syn = { version = "2.0", features = ["full", "parsing", "printing", "proc-macro", "extra-traits"] }
|
||||||
quote = "1"
|
quote = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ note: required by a bound in `rhai::Dynamic::cast`
|
|||||||
| ^^^^^ required by this bound in `Dynamic::cast`
|
| ^^^^^ required by this bound in `Dynamic::cast`
|
||||||
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
||||||
|
|
|
|
||||||
3 | #[derive(Clone)]
|
3 + #[derive(Clone)]
|
||||||
|
4 | struct NonClonable {
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ note: required by a bound in `rhai::Dynamic::cast`
|
|||||||
| ^^^^^ required by this bound in `Dynamic::cast`
|
| ^^^^^ required by this bound in `Dynamic::cast`
|
||||||
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
||||||
|
|
|
|
||||||
3 | #[derive(Clone)]
|
3 + #[derive(Clone)]
|
||||||
|
4 | struct NonClonable {
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ note: required by a bound in `rhai::Dynamic::from`
|
|||||||
= note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
||||||
|
|
|
|
||||||
3 | #[derive(Clone)]
|
3 + #[derive(Clone)]
|
||||||
|
4 | struct NonClonable {
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -15,5 +15,6 @@ note: required by a bound in `rhai::Dynamic::from`
|
|||||||
= note: this error originates in the attribute macro `export_module` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the attribute macro `export_module` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
||||||
|
|
|
|
||||||
3 | #[derive(Clone)]
|
3 + #[derive(Clone)]
|
||||||
|
4 | struct NonClonable {
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ help: a struct with a similar name exists
|
|||||||
| ~~~~~
|
| ~~~~~
|
||||||
help: consider importing one of these items
|
help: consider importing one of these items
|
||||||
|
|
|
|
||||||
11 | use core::fmt::Pointer;
|
11 + use core::fmt::Pointer;
|
||||||
|
|
|
|
||||||
11 | use std::fmt::Pointer;
|
11 + use std::fmt::Pointer;
|
||||||
|
|
|
|
||||||
11 | use syn::__private::fmt::Pointer;
|
11 + use syn::__private::fmt::Pointer;
|
||||||
|
|
|
|
||||||
|
|||||||
3
renovate.json
Normal file
3
renovate.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||||
|
}
|
||||||
@@ -1289,15 +1289,17 @@ impl Engine {
|
|||||||
|
|
||||||
// Call with blank scope
|
// Call with blank scope
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
let this_ptr_not_shared = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
|
let has_non_shared_this_ptr = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
|
||||||
#[cfg(feature = "no_closure")]
|
#[cfg(feature = "no_closure")]
|
||||||
let this_ptr_not_shared = true;
|
let has_non_shared_this_ptr = this_ptr.is_some();
|
||||||
|
|
||||||
// If the first argument is a variable, and there are no curried arguments,
|
// If the first argument is a variable, and there are no curried arguments,
|
||||||
// convert to method-call style in order to leverage potential &mut first argument
|
// convert to method-call style in order to leverage potential &mut first argument
|
||||||
// and avoid cloning the value.
|
// and avoid cloning the value.
|
||||||
match first_arg {
|
match first_arg {
|
||||||
Some(_first_expr @ Expr::ThisPtr(pos)) if curry.is_empty() && this_ptr_not_shared => {
|
Some(_first_expr @ Expr::ThisPtr(pos))
|
||||||
|
if curry.is_empty() && has_non_shared_this_ptr =>
|
||||||
|
{
|
||||||
// Turn it into a method call only if the object is not shared
|
// Turn it into a method call only if the object is not shared
|
||||||
self.track_operation(global, *pos)?;
|
self.track_operation(global, *pos)?;
|
||||||
|
|
||||||
@@ -1381,21 +1383,30 @@ impl Engine {
|
|||||||
let mut first_arg_value = None;
|
let mut first_arg_value = None;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
let this_ptr_not_shared = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
|
let has_non_shared_this_ptr = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
|
||||||
#[cfg(feature = "no_closure")]
|
#[cfg(feature = "no_closure")]
|
||||||
let this_ptr_not_shared = true;
|
let has_non_shared_this_ptr = this_ptr.is_some();
|
||||||
|
|
||||||
// See if the first argument is a variable.
|
// See if the first argument is a variable.
|
||||||
// If so, convert to method-call style in order to leverage potential
|
// If so, convert to method-call style in order to leverage potential
|
||||||
// &mut first argument and avoid cloning the value.
|
// &mut first argument and avoid cloning the value.
|
||||||
match args_expr.get(0) {
|
match args_expr.get(0) {
|
||||||
Some(_first_expr @ Expr::ThisPtr(pos)) if this_ptr_not_shared => {
|
Some(_first_expr @ Expr::ThisPtr(pos)) if has_non_shared_this_ptr => {
|
||||||
self.track_operation(global, *pos)?;
|
self.track_operation(global, *pos)?;
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), _first_expr)?;
|
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), _first_expr)?;
|
||||||
|
|
||||||
// Turn it into a method call only if the object is not shared
|
// The first value is a placeholder (for later if it needs to be cloned)
|
||||||
|
arg_values.push(Dynamic::UNIT);
|
||||||
|
|
||||||
|
for expr in args_expr.iter().skip(1) {
|
||||||
|
let (value, ..) =
|
||||||
|
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
|
||||||
|
arg_values.push(value.flatten());
|
||||||
|
}
|
||||||
|
|
||||||
|
// func(x, ...) -> x.func(...)
|
||||||
let (first, rest) = arg_values.split_first_mut().unwrap();
|
let (first, rest) = arg_values.split_first_mut().unwrap();
|
||||||
first_arg_value = Some(first);
|
first_arg_value = Some(first);
|
||||||
args.push(this_ptr.unwrap());
|
args.push(this_ptr.unwrap());
|
||||||
@@ -1407,7 +1418,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
|
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
|
||||||
|
|
||||||
// func(x, ...) -> x.func(...)
|
// The first value is a placeholder (for later if it needs to be cloned)
|
||||||
arg_values.push(Dynamic::UNIT);
|
arg_values.push(Dynamic::UNIT);
|
||||||
|
|
||||||
for expr in args_expr.iter().skip(1) {
|
for expr in args_expr.iter().skip(1) {
|
||||||
@@ -1423,6 +1434,7 @@ impl Engine {
|
|||||||
args.extend(arg_values.iter_mut());
|
args.extend(arg_values.iter_mut());
|
||||||
} else {
|
} else {
|
||||||
// Turn it into a method call only if the object is not shared and not a simple value
|
// Turn it into a method call only if the object is not shared and not a simple value
|
||||||
|
// func(x, ...) -> x.func(...)
|
||||||
let (first, rest) = arg_values.split_first_mut().unwrap();
|
let (first, rest) = arg_values.split_first_mut().unwrap();
|
||||||
first_arg_value = Some(first);
|
first_arg_value = Some(first);
|
||||||
let obj_ref = target.take_ref().expect("ref");
|
let obj_ref = target.take_ref().expect("ref");
|
||||||
|
|||||||
@@ -246,10 +246,7 @@ impl Dynamic {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_shared(&self) -> bool {
|
pub const fn is_shared(&self) -> bool {
|
||||||
#[cfg(not(feature = "no_closure"))]
|
matches!(self.0, Union::Shared(..))
|
||||||
return matches!(self.0, Union::Shared(..));
|
|
||||||
#[cfg(feature = "no_closure")]
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
/// Is the value held by this [`Dynamic`] a particular type?
|
/// Is the value held by this [`Dynamic`] a particular type?
|
||||||
///
|
///
|
||||||
@@ -2107,6 +2104,8 @@ impl Dynamic {
|
|||||||
#[allow(clippy::only_used_in_recursion)]
|
#[allow(clippy::only_used_in_recursion)]
|
||||||
pub fn deep_scan(&mut self, mut filter: impl FnMut(&mut Self)) {
|
pub fn deep_scan(&mut self, mut filter: impl FnMut(&mut Self)) {
|
||||||
fn scan_inner(value: &mut Dynamic, filter: &mut impl FnMut(&mut Dynamic)) {
|
fn scan_inner(value: &mut Dynamic, filter: &mut impl FnMut(&mut Dynamic)) {
|
||||||
|
filter(value);
|
||||||
|
|
||||||
match &mut value.0 {
|
match &mut value.0 {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(a, ..) => a.iter_mut().for_each(|v| scan_inner(v, filter)),
|
Union::Array(a, ..) => a.iter_mut().for_each(|v| scan_inner(v, filter)),
|
||||||
@@ -2117,7 +2116,6 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter(self);
|
|
||||||
scan_inner(self, &mut filter);
|
scan_inner(self, &mut filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user