Merge 1.9.1 fixes.

This commit is contained in:
Stephen Chung 2022-08-29 22:42:46 +08:00
commit 044484c756
4 changed files with 30 additions and 23 deletions

View File

@ -38,6 +38,14 @@ Enhancements
* `Engine::module_resolver` is added to grant access to the `Engine`'s module resolver. * `Engine::module_resolver` is added to grant access to the `Engine`'s module resolver.
Version 1.9.1
=============
This is a bug-fix version that fixes a bug.
Accessing properties in _Strict Variables Mode_ no longer generates a _variable not found_ error.
Version 1.9.0 Version 1.9.0
============= =============

View File

@ -3,7 +3,7 @@ members = [".", "codegen"]
[package] [package]
name = "rhai" name = "rhai"
version = "1.9.0" version = "1.9.1"
rust-version = "1.61.0" rust-version = "1.61.0"
edition = "2018" edition = "2018"
resolver = "2" resolver = "2"

View File

@ -1311,6 +1311,7 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
is_property: bool,
settings: ParseSettings, settings: ParseSettings,
) -> ParseResult<Expr> { ) -> ParseResult<Expr> {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
@ -1451,11 +1452,11 @@ impl Engine {
|crate::ast::Ident { name, pos }| { |crate::ast::Ident { name, pos }| {
let (index, is_func) = state.access_var(name, lib, *pos); let (index, is_func) = state.access_var(name, lib, *pos);
if settings.options.contains(LangOptions::STRICT_VAR) if !is_func
&& !settings.in_closure
&& index.is_none() && index.is_none()
&& !settings.in_closure
&& settings.options.contains(LangOptions::STRICT_VAR)
&& !state.scope.contains(name) && !state.scope.contains(name)
&& !is_func
{ {
// If the parent scope is not inside another capturing closure // If the parent scope is not inside another capturing closure
// then we can conclude that the captured variable doesn't exist. // then we can conclude that the captured variable doesn't exist.
@ -1588,20 +1589,18 @@ impl Engine {
// Once the identifier consumed we must enable next variables capturing // Once the identifier consumed we must enable next variables capturing
state.allow_capture = true; state.allow_capture = true;
} }
Expr::Variable( let name = state.get_interned_string(s);
(None, ns, 0, state.get_interned_string(s)).into(), Expr::Variable((None, ns, 0, name).into(), None, settings.pos)
None,
settings.pos,
)
} }
// Normal variable access // Normal variable access
_ => { _ => {
let (index, is_func) = state.access_var(&s, lib, settings.pos); let (index, is_func) = state.access_var(&s, lib, settings.pos);
if settings.options.contains(LangOptions::STRICT_VAR) if !is_property
&& index.is_none()
&& !state.scope.contains(&s)
&& !is_func && !is_func
&& index.is_none()
&& settings.options.contains(LangOptions::STRICT_VAR)
&& !state.scope.contains(&s)
{ {
return Err( return Err(
PERR::VariableUndefined(s.to_string()).into_err(settings.pos) PERR::VariableUndefined(s.to_string()).into_err(settings.pos)
@ -1615,11 +1614,8 @@ impl Engine {
None None
} }
}); });
Expr::Variable( let name = state.get_interned_string(s);
(index, ns, 0, state.get_interned_string(s)).into(), Expr::Variable((index, ns, 0, name).into(), short_index, settings.pos)
short_index,
settings.pos,
)
} }
} }
} }
@ -1806,7 +1802,7 @@ impl Engine {
(.., pos) => return Err(PERR::PropertyExpected.into_err(*pos)), (.., pos) => return Err(PERR::PropertyExpected.into_err(*pos)),
} }
let rhs = self.parse_primary(input, state, lib, settings.level_up())?; let rhs = self.parse_primary(input, state, lib, true, settings.level_up())?;
let op_flags = match op { let op_flags = match op {
Token::Period => ASTFlags::NONE, Token::Period => ASTFlags::NONE,
Token::Elvis => ASTFlags::NEGATED, Token::Elvis => ASTFlags::NEGATED,
@ -1976,7 +1972,7 @@ impl Engine {
// <EOF> // <EOF>
Token::EOF => Err(PERR::UnexpectedEOF.into_err(settings.pos)), Token::EOF => Err(PERR::UnexpectedEOF.into_err(settings.pos)),
// All other tokens // All other tokens
_ => self.parse_primary(input, state, lib, settings.level_up()), _ => self.parse_primary(input, state, lib, false, settings.level_up()),
} }
} }

View File

@ -56,10 +56,6 @@ fn test_options_allow() -> Result<(), Box<EvalAltResult>> {
fn test_options_strict_var() -> Result<(), Box<EvalAltResult>> { fn test_options_strict_var() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new(); let mut engine = Engine::new();
let mut scope = Scope::new();
scope.push("x", 42 as INT);
scope.push_constant("y", 0 as INT);
engine.compile("let x = if y { z } else { w };")?; engine.compile("let x = if y { z } else { w };")?;
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
@ -78,9 +74,16 @@ fn test_options_strict_var() -> Result<(), Box<EvalAltResult>> {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
engine.compile("let f = |y| x * y;")?; engine.compile("let f = |y| x * y;")?;
let mut scope = Scope::new();
scope.push("x", 42 as INT);
scope.push_constant("y", 0 as INT);
engine.set_strict_variables(true); engine.set_strict_variables(true);
assert!(engine.compile("let x = if y { z } else { w };").is_err()); assert!(engine.compile("let x = if y { z } else { w };").is_err());
engine.compile_with_scope(&mut scope, "if x.abs() { y } else { x + y.len };")?;
engine.compile("let y = 42; let x = y;")?; engine.compile("let y = 42; let x = y;")?;
assert_eq!( assert_eq!(