Denoのreplをブラウザコンソールから使う

Denoのコマンドラインフラグの中に`deno repl --inspect`というのを発見。使ってみたらいい感じだった。

## 使い方

```:コマンドライン
$ deno repl --inspect
Debugger listening on ws://127.0.0.1:9229/ws/595bd5b5-17d9-471e-baa0-ec369fca365b
Deno 1.10.0+5792778
exit using ctrl+d or close()
> Debugger session started.
```

とコマンドを打ってからChromeの開発者ツールを開く。
左上にNode.jsの六角形マークが表示されているのでクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/133cbea9-9beb-e93b-56b4-f3c130e9ea72.png)
すると、Node.jsという名前でDenoのreplが開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/47137531-f880-7615-4415-d23f89323987.png)

`Deno.***`のAPIたちが見えているので間違いなくDenoランタイムで動いているコードだ。

なぜNode.jsと左上に表示されているのかというと、[inspectorプロトコル上でNode.jsを装うことでdevtoolの表示が改善できるから](https://github.com/denoland/deno/pull/10115)っぽい。

`chrome://inspect/#devices`にアクセスしてdevicesからdenoを選択しても同じ結果が得られる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/036aa3de-bd73-4e68-c345-7fa846f51e67.png)

とりあえず何かしらのreplが開きたい時に便利。メリットは

 - ローカルファイルにアクセスできる
 - デフォルトでfetchを使える（CORSを気にする必要なし）
 - requireする必要なし

みたいなところかな。
~~デメリットとしては、`console.log`してもChrome側に表示されないのが不便、というのがある。（現在[実装待ち](https://github.com/denoland/deno/issues/4502)）~~ →[実装されました](https://github.com/denoland/deno/pull/11134)

## おまけ：この画面を自動で開きたい

コマンドを打ってからウィンドウを毎回切り替えるのは面倒。スタートメニューからワンクリックで起動できないだろうか。

色々調べると
① `http://127.0.0.1:9229/json`にアクセスする
② ①で返ってくるjsonを元に`devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/ws/<ここにuuid>&experiments=true&v8only=true`というURLにアクセスする
という方法で開けることが分かった。

#### 試した①

javscriptブックマーク

→ブックマークにjavascriptを登録するのが一番簡単そう。しかし、`devtools://`以下のURLへのアクセスは弾かれる。この方法は使えない。

#### 試した②

puppeteer

→同じく`devtools://`以下のURLは弾かれてダメだった。

#### 試した③

Chrome拡張

似たことをしているChrome拡張に[NIM](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj)と[rawkit](https://chrome.google.com/webstore/detail/rawkit/poapmlldjpcgenaedpopfjjagnihpkim)がある。が、前者はなんか動かず、後者はNodeのみ対応ということで使えなかった。

最終的にchrome拡張を自作することに。
background scriptからなら`devtools://`以下のページを操作することができそう。

バックグラウンドから1秒間隔で`http://127.0.0.1:9229/json`にアクセスし、
・inspectorの情報が返ってくればdevtoolタブを開く
・返ってこなければdevtoolタブを閉じる
という実装をする。

した。

```:フォルダ構成
extension/
├manifest.json
└background.js
```

```manifest.json
{
  "name": "Deno Debugger Open",
  "version": "1.0.0",
  "manifest_version": 2,
  "description": "Deno Debugger Open",
  "permissions": ["tabs", "debugger", "<all_urls>"],
  "background": {
    "scripts": ["background.js"]
  }
}
```

```background.js
// @ts-check

//chrome拡張の型定義
/// <reference path="https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/types/chrome/index.d.ts"/>

/**
 * devtoolのURL (例：devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/ws/d54be582-ca29-4117-b631-dbbd4e5c9bef&experiments=true&v8only=true)
 * @type {string}
 */
let url;
setInterval(async () => {
  /**
	 * devtoolのタブを開くかどうか
	 * @type {boolean}
	 */
  let shouldOpen;
  try {
    /**
     * @type {[{"devtoolsFrontendUrl":string}]}
     */
    const json = await (await fetch("http://127.0.0.1:9229/json")).json();
    url = json[0].devtoolsFrontendUrl;
    shouldOpen = true;
  } catch (_) {
    shouldOpen = false;
  }
  url && chrome.tabs.query({ url }, (tabs) => {
    if (shouldOpen) {
      if (!tabs.length) {
        console.log("open: ", url);
        chrome.tabs.create({ url });
      }
    } else {
      for (const tab of tabs) {
        console.log("close: ", url);
        tab.id && chrome.tabs.remove(tab.id);
      }
    }
  });
}, 1000);
```

これを拡張機能として登録すると、replの起動を検知した時にブラウザの画面いっぱいにconsoleの画面が自動で開くようになるはず。

ところで、Deno用のエディタ拡張を入れておけばJavaScriptに対してもTypeScriptと同等の型定義や補完が効く。
コード中ではgithubからchrome拡張向けの型定義ファイルを拾ってきて利用している。（`/// <reference path="https://raw.githubusercontent.com/..."/>`の行）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/b4ae1324-e618-da3f-9b4d-727541644fc5.png)

最後に、replの起動ボタンをスタートメニューに追加する。
ショートカットを作って、右クリック→スタートメニューに追加 でOK。

```:ショートカットのリンク先
C:\Windows\System32\cmd.exe /c deno repl --inspect
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/29fd5f98-b700-5229-d3f8-87d7dffd9f45.png)

これでスタートメニュからワンクリックでreplを開けるようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/1cf5fd7a-871c-ef6c-e2d7-ba43e2d55040.png)

~~今気づいたけどパーミッション指定(`--allow-hoge`)忘れてるな…~~replはパーミッション指定が不要だった。