<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::js::JSRef;
use dom::bindings::utils::Reflectable;

use dom::window::ScriptHelpers;

use script_task::{ScriptChan, ScriptMsg, TimerSource};

use util::task::spawn_named;
use util::str::DOMString;

use js::jsval::JSVal;

use std::borrow::ToOwned;
use std::cell::Cell;
use std::cmp;
use std::collections::HashMap;
use std::sync::mpsc::{channel, Sender};
use std::sync::mpsc::Select;
use std::hash::{Hash, Hasher, Writer};
use std::old_io::timer::Timer;
use std::time::duration::Duration;

#[derive(PartialEq, Eq)]
#[jstraceable]
#[derive(Copy)]
pub struct TimerId(i32);

#[jstraceable]
#[privatize]
struct TimerHandle {
    handle: TimerId,
    data: TimerData,
    control_chan: Option<Sender<TimerControlMsg>>,
}

#[jstraceable]
#[derive(Clone)]
pub enum TimerCallback {
    StringTimerCallback(DOMString),
    FunctionTimerCallback(Function)
}

impl<H: Writer + Hasher> Hash<H> for TimerId {
    fn hash(&self, state: &mut H) {
        let TimerId(id) = *self;
        id.hash(state);
    }
}

impl TimerHandle {
    fn cancel(&mut self) {
        self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Cancel).ok());
    }
    fn suspend(&mut self) {
        self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Suspend).ok());
    }
    fn resume(&mut self) {
        self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Resume).ok());
    }
}

#[jstraceable]
#[privatize]
pub struct TimerManager {
    active_timers: DOMRefCell<HashMap<TimerId, TimerHandle>>,
    next_timer_handle: Cell<i32>,
}


#[unsafe_destructor]
impl Drop for TimerManager {
    fn drop(&mut self) {
        for (_, timer_handle) in self.active_timers.borrow_mut().iter_mut() {
            timer_handle.cancel();
        }
    }
}

// Enum allowing more descriptive values for the is_interval field
#[jstraceable]
#[derive(PartialEq, Copy, Clone)]
pub enum IsInterval {
    Interval,
    NonInterval,
}

// Messages sent control timers from script task
#[jstraceable]
#[derive(PartialEq, Copy, Clone, Show)]
pub enum TimerControlMsg {
    Cancel,
    Suspend,
    Resume
}

// Holder for the various JS values associated with setTimeout
// (ie. function value to invoke and all arguments to pass
//      to the function when calling it)
// TODO: Handle rooting during fire_timer when movable GC is turned on
#[jstraceable]
#[privatize]
#[derive(Clone)]
struct TimerData {
    is_interval: IsInterval,
    callback: TimerCallback,
    args: Vec<JSVal>
}

impl TimerManager {
    pub fn new() -> TimerManager {
        TimerManager {<commit_msg>auto merge of #5048 : servo/servo/show-warning, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::js::JSRef;
use dom::bindings::utils::Reflectable;

use dom::window::ScriptHelpers;

use script_task::{ScriptChan, ScriptMsg, TimerSource};

use util::task::spawn_named;
use util::str::DOMString;

use js::jsval::JSVal;

use std::borrow::ToOwned;
use std::cell::Cell;
use std::cmp;
use std::collections::HashMap;
use std::sync::mpsc::{channel, Sender};
use std::sync::mpsc::Select;
use std::hash::{Hash, Hasher, Writer};
use std::old_io::timer::Timer;
use std::time::duration::Duration;

#[derive(PartialEq, Eq)]
#[jstraceable]
#[derive(Copy)]
pub struct TimerId(i32);

#[jstraceable]
#[privatize]
struct TimerHandle {
    handle: TimerId,
    data: TimerData,
    control_chan: Option<Sender<TimerControlMsg>>,
}

#[jstraceable]
#[derive(Clone)]
pub enum TimerCallback {
    StringTimerCallback(DOMString),
    FunctionTimerCallback(Function)
}

impl<H: Writer + Hasher> Hash<H> for TimerId {
    fn hash(&self, state: &mut H) {
        let TimerId(id) = *self;
        id.hash(state);
    }
}

impl TimerHandle {
    fn cancel(&mut self) {
        self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Cancel).ok());
    }
    fn suspend(&mut self) {
        self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Suspend).ok());
    }
    fn resume(&mut self) {
        self.control_chan.as_ref().map(|chan| chan.send(TimerControlMsg::Resume).ok());
    }
}

#[jstraceable]
#[privatize]
pub struct TimerManager {
    active_timers: DOMRefCell<HashMap<TimerId, TimerHandle>>,
    next_timer_handle: Cell<i32>,
}


#[unsafe_destructor]
impl Drop for TimerManager {
    fn drop(&mut self) {
        for (_, timer_handle) in self.active_timers.borrow_mut().iter_mut() {
            timer_handle.cancel();
        }
    }
}

// Enum allowing more descriptive values for the is_interval field
#[jstraceable]
#[derive(PartialEq, Copy, Clone)]
pub enum IsInterval {
    Interval,
    NonInterval,
}

// Messages sent control timers from script task
#[jstraceable]
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum TimerControlMsg {
    Cancel,
    Suspend,
    Resume
}

// Holder for the various JS values associated with setTimeout
// (ie. function value to invoke and all arguments to pass
//      to the function when calling it)
// TODO: Handle rooting during fire_timer when movable GC is turned on
#[jstraceable]
#[privatize]
#[derive(Clone)]
struct TimerData {
    is_interval: IsInterval,
    callback: TimerCallback,
    args: Vec<JSVal>
}

impl TimerManager {
    pub fn new() -> TimerManager {
        TimerManager {
{'fraction_non_alphanumeric': 0.1398283695103483, 'fraction_numerical': 0.003365303718660609, 'mean_word_length': 4.413479052823315, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4482652', 'n_tokens_mistral': 2003, 'n_tokens_neox': 1997, 'n_words': 499}