evil-timer.js の紹介

<https://github.com/wraith13/evil-timer.js>

[evil-timer.js](https://github.com/wraith13/evil-timer.js) はテストやデバッグの為に JavaScript 上の時間をコントロールする為のものです。

時間停止したり、時間の経過速度を速くしたり遅くしたりする事で、通常であれば やり難い以下のような場面での動作確認、JavaScript のデバッグ、CSS の調整が楽に行えるようになります。

- 初期状態( `setTimeout` や `setInterval` が実行される前の )
- 瞬間的な挙動( `setTimeout` や `setInterval` のステップ実行 )
- トーストのような僅かな時間しか表示されない UI の挙動
- １時間に１回、１日に１回、１ヶ月に１回、１年に１回といった極稀なイベントに起因する挙動
- システムクロックの自動調整によって発生する、時間の逆転イベント(システムクロックが数秒前に戻る)
- システムクロックが大幅にズレてる環境の挙動

## 組み込み方

HTMLの head タグ内で次のような記述を行ってください。( JavaScript ファイルをコピーして中身を直接 HTML ファイルに埋め込んでも構いません。 )

```html
<script src="https://wraith13.github.io/evil-timer.js/index.js"></script>
```

`Date`, `setTimeout`, `setInterval` を使用する前に読み込ませる必要があります。

## URL引数によるデモ

第三者による悪意あるリンクが作成/拡散されるの防ぐ為、 default では URL 引数は無効になっています。

一度、Web ブラウザでアクセスして JavaScript コンソールから次のコマンドを実行することで URL 引数による指定が有効になります。
 
 ```js
EvilTimer.debugOn();
```

HTML内で次のように設定しておくと初めから URL 引数が利用できますが、第三者による悪意あるリンクの作成/拡散ができてしまうので、ローカル環境 or クローズド環境でのテスト時以外でこれをやる事は推奨できません。 ( ちなみにこの形で `debug` を `false` に指定しておくと、 `EvilTimer.debugOn()` を実行しても HTML が読み込まれる度にデバッグモードがオフになる為、 URL 引数の利用を禁止できます。 )

```html
<script>
const evilTimerConfig =
{
    debug: true,
};
</script>
<script src="https://wraith13.github.io/evil-timer.js/index.js"></script>
```

 
- [通常(指定無し)](https://wraith13.github.io/clockworks/#RainbowClock)

まず上の素の URL でアクセスし、JavaScript コンソールから `EvilTimer.debugOn();` を実行してデバッグモードを有効にしてください。その後、以下の URL にアクセスすると、いろいろ試すことができます。

- [スピード x1000 ( ?evil-timer={"speed":1000} )](https://wraith13.github.io/clockworks/?evil-timer={"speed":1000}#RainbowClock)
- [スピード x1/2 ( ?evil-timer={"speed":0.5} )](https://wraith13.github.io/clockworks/?evil-timer={"speed":0.5}#RainbowClock)
- [時間停止 ( ?evil-timer={"pause":true} )](https://wraith13.github.io/clockworks/?evil-timer={"pause":true}#RainbowClock)
- [スピード x-1000(時間逆行) ( ?evil-timer={"speed":-1000} )](https://wraith13.github.io/clockworks/?evil-timer={"speed":-1000}#RainbowClock)
- [2000年01月01日00時00分00秒 ( ?evil-timer={"date":"2000-01-01T00:00:00"} )](https://wraith13.github.io/clockworks/?evil-timer={"date":"2000-01-01T00:00:00"}#RainbowClock)
- [組み合わせ ( ?evil-timer={"speed":1000,"pause":true,"date":"2000-01-01T00:00:00"} )](https://wraith13.github.io/clockworks/?evil-timer={"speed":1000,"pause":true,"date":"2000-01-01T00:00:00"}#RainbowClock)

※ このリンク先のサイトは開発中の Web アプリである為、予告無くいろいろ機能しなくなる可能性があります。

## Web ブラウザの JavaScript コンソールから

全てのコマンドは [README](https://github.com/wraith13/evil-timer.js/blob/master/README.ja.md) を参照して頂くとして、幾つか抜粋して簡単に紹介します。

### 現在日時指定

```js
EvilTimer.setDate(new Date(2022,1,22,22,22,22)); // Date オブジェクトでの指定
EvilTimer.setDate("2022-02-22T22:22:22"); // 文字列での指定
EvilTimer.setDate(1645536142000); // 数値での指定
EvilTimer.resetDate(); // システム時刻に戻す
```

※ `EvilTimer.pause()` で時間停止状態になっていない場合、 `EvilTimer.setSpeed()` で指定されてるスピードに従って自動的に時間経過します。

### 時間経過スピード指定

```js
EvilTimer.setSpeed(1000); // 1000倍
EvilTimer.setSpeed(0.01); // 1/100倍
EvilTimer.setSpeed(0); // 時間停止( EvilTimer.pause() と同じ )
EvilTimer.setSpeed(-1000); // 1000倍で時間逆行
```

※ `setTimeout` や `setInterval` の動作時間にも影響しますが、既に設定されているタイマーの起動タイミングを変更する事はできない点にご注意ください。 5分後に動作するように設定( `setTimeout(..., 300000)` )された後から `EvilTimer.setSpeed(1000)` しても、5分後に動作する事は変更できません。この為、時間経過スピードを指定したい場合はページロード時に設定される URL 引数で指定する事が好ましいです。

### 時間停止 / ステップ実行

```js
EvilTimer.pause(); // 時間一時停止
EvilTimer.step(); // 保留されてるタスクを１つだけ実行
EvilTimer.stepAll(); // 保留されてるタスクを全部実行(実行中に追加された分は実行しない)
EvilTimer.stepOut(); // 保留されてるタスクを全部実行(実行中に追加された分も実行する)
EvilTimer.unpause();// 時間一時停止解除
```

### 復元

```js
EvilTimer.restore(); // EvilTimer.setSpeed(1) + EvilTimer.unpause() + EvilTimer.resetDate() と同じ
```

### ステータス取得

```js
EvilTimer.getStatus();
```

次のような JSON を返します。

```json
{
    "enabled": true,
    "debug": true,
    "speed": 1000,
    "isPaused": true,
    "susppendedTasksCount": 2,
    "date":
    {
        "vanilla":
        {
            "text": "2023/5/29 23:54:41",
            "tick": 1685372081785
        },
        "evil":
        {
            "text": "2023/5/31 16:06:07",
            "tick": 1685516767640
        }
    }
}
```

## ロードメッセージの抑止

evil-timer.js を組み込むと default で次のようなメッセージが Web ブラウザのコンソールに出力されます。

>evil-timer.js is loaded. You can use EvilTimer commands with your own risk. see: https://github.com/wraith13/evil-timer.js

このメッセージの出力を抑止したい場合は evil-timer.js が **読み込まれる前に** 次のように `disabledLoadMessage` に `true` を指定してください。

```html
<script>
const evilTimerConfig =
{
    disabledLoadMessage: true,
};
</script>
<script src="https://wraith13.github.io/evil-timer.js/index.js"></script>
```

この `evilTimerConfig` は URL 引数で指定する JSON と同じ型なので、 `speed`, `pause`, `date` をここで指定する事もできます。 (  URL 引数では無視される `debug` 指定も、こちらであれば機能します。 )

尚、 URL 引数の指定が存在した場合、 URL 引数が優先され、 `evilTimerConfig` は URL 引数で指定されてない項目も含めて完全に無視されます。