core,avm2: Make Timer.setDelay not change the timer ID. Fix #15005.

This commit is contained in:
TÖRÖK Attila 2024-02-25 14:42:52 +01:00
parent e288375543
commit ee0c1f42ff
3 changed files with 56 additions and 3 deletions

View File

@ -32,11 +32,12 @@ package flash.utils {
this.checkDelay(delay);
this._delay = value;
if (this.running) {
this.stop();
this.start();
this.updateDelay();
}
}
private native function updateDelay():void;
public function get repeatCount(): int {
return this._repeatCount;
}

View File

@ -81,3 +81,32 @@ pub fn start<'gc>(
}
Ok(Value::Undefined)
}
/// Implements `Timer.updateDelay`
pub fn update_delay<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let id = this
.get_property(
&Multiname::new(activation.avm2().flash_utils_internal, "_timerId"),
activation,
)
.unwrap()
.coerce_to_i32(activation)?;
let delay = this
.get_property(
&Multiname::new(activation.avm2().flash_utils_internal, "_delay"),
activation,
)
.unwrap()
.coerce_to_i32(activation)?;
if id != -1 {
activation.context.timers.set_delay(id, delay);
}
Ok(Value::Undefined)
}

View File

@ -258,6 +258,29 @@ impl<'gc> Timers<'gc> {
len < old_len
}
/// Changes the delay of a timer.
pub fn set_delay(&mut self, id: i32, interval: i32) {
// SANITY: Set a minimum interval so we don't spam too much.
let interval = interval.max(Self::MIN_INTERVAL) as u64 * (Self::TIMER_SCALE as u64);
// Due to the limitations of `BinaryHeap`, we have to do this in a slightly roundabout way.
let mut timer = None;
for t in self.timers.iter() {
if t.id == id {
timer = Some(t.clone());
break;
}
}
if let Some(mut timer) = timer {
self.remove(id);
timer.interval = interval;
self.timers.push(timer);
} else {
panic!("Changing delay of non-existent timer");
}
}
fn peek(&self) -> Option<&Timer<'gc>> {
self.timers.peek()
}
@ -286,7 +309,7 @@ unsafe impl<'gc> Collect for Timers<'gc> {
}
/// A timer created via `setInterval`/`setTimeout`.
/// Runs a callback when it ticks.
#[derive(Collect)]
#[derive(Clone, Collect)]
#[collect(no_drop)]
pub struct Timer<'gc> {
/// The ID of the timer.