diff --git a/CHANGELOG.md b/CHANGELOG.md index f0d85f74..19f4bb28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,14 @@ Enhancements * `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 ============= diff --git a/Cargo.toml b/Cargo.toml index 2078eb79..54331e51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "codegen"] [package] name = "rhai" -version = "1.9.0" +version = "1.9.1" rust-version = "1.61.0" edition = "2018" resolver = "2" diff --git a/src/parser.rs b/src/parser.rs index 216cd3ea..43df65a1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1311,6 +1311,7 @@ impl Engine { input: &mut TokenStream, state: &mut ParseState, lib: &mut FnLib, + is_property: bool, settings: ParseSettings, ) -> ParseResult { #[cfg(not(feature = "unchecked"))] @@ -1451,11 +1452,11 @@ impl Engine { |crate::ast::Ident { name, pos }| { let (index, is_func) = state.access_var(name, lib, *pos); - if settings.options.contains(LangOptions::STRICT_VAR) - && !settings.in_closure + if !is_func && index.is_none() + && !settings.in_closure + && settings.options.contains(LangOptions::STRICT_VAR) && !state.scope.contains(name) - && !is_func { // If the parent scope is not inside another capturing closure // 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 state.allow_capture = true; } - Expr::Variable( - (None, ns, 0, state.get_interned_string(s)).into(), - None, - settings.pos, - ) + let name = state.get_interned_string(s); + Expr::Variable((None, ns, 0, name).into(), None, settings.pos) } // Normal variable access _ => { let (index, is_func) = state.access_var(&s, lib, settings.pos); - if settings.options.contains(LangOptions::STRICT_VAR) - && index.is_none() - && !state.scope.contains(&s) + if !is_property && !is_func + && index.is_none() + && settings.options.contains(LangOptions::STRICT_VAR) + && !state.scope.contains(&s) { return Err( PERR::VariableUndefined(s.to_string()).into_err(settings.pos) @@ -1615,11 +1614,8 @@ impl Engine { None } }); - Expr::Variable( - (index, ns, 0, state.get_interned_string(s)).into(), - short_index, - settings.pos, - ) + let name = state.get_interned_string(s); + Expr::Variable((index, ns, 0, name).into(), short_index, settings.pos) } } } @@ -1806,7 +1802,7 @@ impl Engine { (.., 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 { Token::Period => ASTFlags::NONE, Token::Elvis => ASTFlags::NEGATED, @@ -1976,7 +1972,7 @@ impl Engine { // Token::EOF => Err(PERR::UnexpectedEOF.into_err(settings.pos)), // All other tokens - _ => self.parse_primary(input, state, lib, settings.level_up()), + _ => self.parse_primary(input, state, lib, false, settings.level_up()), } } diff --git a/tests/options.rs b/tests/options.rs index 27ff3ca2..8bc27a1d 100644 --- a/tests/options.rs +++ b/tests/options.rs @@ -56,10 +56,6 @@ fn test_options_allow() -> Result<(), Box> { fn test_options_strict_var() -> Result<(), Box> { 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 };")?; #[cfg(not(feature = "no_function"))] @@ -78,9 +74,16 @@ fn test_options_strict_var() -> Result<(), Box> { #[cfg(not(feature = "no_function"))] 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); 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;")?; assert_eq!(