Fix bug in calling script function in method style.
This commit is contained in:
parent
acd4685145
commit
9616452c00
@ -618,8 +618,31 @@ impl Engine {
|
|||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if !native_only {
|
if !native_only {
|
||||||
if let Some(fn_def) = lib.get(&hashes.1) {
|
if let Some(fn_def) = lib.get(&hashes.1) {
|
||||||
|
let mut this_copy: Option<Dynamic>;
|
||||||
|
let mut this_pointer: Option<&mut Dynamic> = None;
|
||||||
|
|
||||||
|
if is_ref && !args.is_empty() {
|
||||||
|
// Clone the original value. It'll be consumed because the function
|
||||||
|
// is pure and doesn't know that the first value is a reference (i.e. `is_ref`)
|
||||||
|
this_copy = Some(args[0].clone());
|
||||||
|
|
||||||
|
// Replace the first reference with a reference to the clone, force-casting the lifetime.
|
||||||
|
// Keep the original reference. Must remember to restore it before existing this function.
|
||||||
|
this_pointer = Some(mem::replace(
|
||||||
|
args.get_mut(0).unwrap(),
|
||||||
|
unsafe_mut_cast_to_lifetime(this_copy.as_mut().unwrap()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run scripted function
|
||||||
let result =
|
let result =
|
||||||
self.call_script_fn(scope, state, lib, fn_name, fn_def, args, pos, level)?;
|
self.call_script_fn(scope, state, lib, fn_name, fn_def, args, pos, level)?;
|
||||||
|
|
||||||
|
// Restore the original reference
|
||||||
|
if let Some(this_pointer) = this_pointer {
|
||||||
|
mem::replace(args.get_mut(0).unwrap(), this_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
return Ok((result, false));
|
return Ok((result, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1577,6 +1600,7 @@ impl Engine {
|
|||||||
// Normal function call - except for eval (handled above)
|
// Normal function call - except for eval (handled above)
|
||||||
let mut arg_values: StaticVec<Dynamic>;
|
let mut arg_values: StaticVec<Dynamic>;
|
||||||
let mut args: StaticVec<_>;
|
let mut args: StaticVec<_>;
|
||||||
|
let mut is_ref = false;
|
||||||
|
|
||||||
if args_expr.is_empty() {
|
if args_expr.is_empty() {
|
||||||
// No arguments
|
// No arguments
|
||||||
@ -1602,6 +1626,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
args = once(target).chain(arg_values.iter_mut()).collect();
|
args = once(target).chain(arg_values.iter_mut()).collect();
|
||||||
|
|
||||||
|
is_ref = true;
|
||||||
}
|
}
|
||||||
// func(..., ...)
|
// func(..., ...)
|
||||||
_ => {
|
_ => {
|
||||||
@ -1617,7 +1643,7 @@ impl Engine {
|
|||||||
|
|
||||||
let args = args.as_mut();
|
let args = args.as_mut();
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, name, *native, *hash, args, false, def_val, *pos, level,
|
state, lib, name, *native, *hash, args, is_ref, def_val, *pos, level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,23 @@ fn test_functions() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(engine.eval::<INT>("fn add(x, n) { x + n } add(40, 2)")?, 42);
|
assert_eq!(engine.eval::<INT>("fn add(x, n) { x + n } add(40, 2)")?, 42);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>("fn add(x, n) { x + n } let a = 40; add(a, 2); a")?,
|
||||||
|
40
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
engine.eval::<INT>("fn add(x, n) { x + n } let x = 40; x.add(2)")?,
|
engine.eval::<INT>("fn add(x, n) { x + n } let x = 40; x.add(2)")?,
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>("fn add(x, n) { x += n; } let x = 40; x.add(2); x")?,
|
||||||
|
40
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(engine.eval::<INT>("fn mul2(x) { x * 2 } mul2(21)")?, 42);
|
assert_eq!(engine.eval::<INT>("fn mul2(x) { x * 2 } mul2(21)")?, 42);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -21,5 +32,11 @@ fn test_functions() -> Result<(), Box<EvalAltResult>> {
|
|||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>("fn mul2(x) { x *= 2; } let x = 21; x.mul2(); x")?,
|
||||||
|
21
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user