MDN にくまがいた
https://github.com/mdn/kuma

恐竜でもきつねでもなくて くま
MDN のサイトを作ってるものみたい?
KumaScript なるものもあった
こういう MDN のページはこのスクリプトで書かれてるのかな
Wiki みたいな一般的な記法かと思ってた


よく考えたら kuma って日本語じゃん
Sushi Browser
なんか見つけた謎のブラウザ
https://sushib.me/ja/

Chromium 系ブラウザは色々あっても基本は Chromium なのですがこれは Electron ベースのようです
Node.js が使えるということはローカルアクセスなどブラウザではできない機能が豊富そうです
特にターミナルが使えているのが特徴的

コンセプトは 通常のブラウザでは画面がもったいないから最大限効率化したいということみたいです
効率化しすぎた結果なのかサンプル画面を見てもレイアウトがどうなってるのかよくわからないくらいレベルです
renderer プロセスの HTML で Grid 使ってコントロールや webview いっぱい配置した感じなのでしょうか

思いつきで作ったまま放置されてそうな予感はしたのですがそれなりの期間更新されてるようですし 新しいタイプのブラウザとして使ってみるのはありなのかも?
fs/promises は使えなくなってた
以前 fs のメソッドの Promise 版は fs/promises を require してました
いつのまにか fs.promises ができてて fs をインポートしたら一緒に使えるからこっちを使ってましたが fs/promises はどうなってるんだろうと require したら見つかりませんでした

調べてみたら
https://github.com/nodejs/node/pull/20504

どっちも使えるわけではなく fs.promises に変更だったみたいです

ちなみに fs.promises のインポートでたまに見かけるこれですが

import { promises as fs } from "fs"

fs.existsSync など promises にないメソッドが使えないので fs 自体を変数に持ってたほうがいいと思います
Node.js の http parser が変わってた
Node.js 12 から llhttp に変わってたみたい
これまでの http-parser

元のは C 言語で書かれててメンテが辛かったとか
新しいのは一部が C 言語で大部分が TypeScript
書きやすさ重視で速度はそんなでもないのかと思ったけど 156% 速くなってるみたい

llparser という別のプロジェクトも出てきていまいちわかってないけど
llparser は http 関係なく C 言語や LLVM のビットコードでパーサ自体を作るものみたいだし llhttp は llparser を使って C 言語を出力してそれを実行してるということかな
ベンチマークの llhttp に (C) て書いてるし

Node.js ユーザ的には関係ないことでただ速くなったんだー くらいに思ってれば良さそうなのでこれ以上の詳しいことは調べてない
コマンドライン環境で JSON フォーマットしたい
自動生成された圧縮された JSON をみたいのですが インデントもない状態だと読むのが辛いです
短ければコピペして手元の Windows でフォーマットすればいいのですがちょっと長めです
ローカルまでコピーしてくるのも面倒ですし フォーマットするツールをインストールするのもできれば避けたいです

いい方法ないものかと探してみると Python でできました

python3 -m json.tool min.json

これで min.json をフォーマットして表示できます
デフォルトでいろいろな機能が揃ってるのでやっぱり Python は便利ですね
CentOS8 はデフォルトで入ってないのが残念ですが これくらいなら platform-python 使ってしまって良いかも

注意したいのは 複数指定できないところです

python3 -m json.tool a.json b.json

とすると 2 つを見れるのではなく b.json へ出力となって もとの b.json は消えてしまいます

使い方

user@ubuntu ~> python3 -m json.tool --help
usage: python -m json.tool [-h] [--sort-keys] [infile] [outfile]

A simple command line interface for json module to validate and pretty-print
JSON objects.

positional arguments:
infile a JSON file to be validated or pretty-printed
outfile write the output of infile to outfile

optional arguments:
-h, --help show this help message and exit
--sort-keys sort the output of dictionaries alphabetically by key
Blob に text と arrayBuffer メソッドが増えてた
const b = new Blob([["abcd"]])
console.log(await b.text())
// abcd
console.log(new Uint8Array(await b.arrayBuffer()))
// Uint8Array(4) [97, 98, 99, 100]

FileReader が基本いらなくなる
BinaryString と DataURL 形式は対応してないからこれらが必要なら FileReader を使う
ArrayBuffer から変換もできる

const ab = new ArrayBuffer()
const binary_string = Array.from(new Uint8Array(ab), x => String.fromCharCode(x)).join("")
const data_url = "data:application/octet-stream;base64," + btoa(binary_string)
BigInt 使うときの一時変数に n は使わないほうが良さそう
一行で済む関数くらいなら 引数に変に長い名前を入れるより 1 文字のほうがスッキリ見やすいので 1 文字だけの名前を使うことは多いです
map,filter,forEach などだと e を使うことが多くて reduce や sort だと a, b とか
数値だと num ということで n を使うこともあるのですが BigInt と組み合わせるとかなり見づらい事に気づきました

const fn = n => (n - 1n) * (n / 2n) + (n % 2n) * (n / 2n)

数学では 2 * n を 2n と書くのでそれっぽく見えてしまいます

ちなみにこの関数は引数の数までの自然数を合計したものを返す関数で特に意味はないです
3 なら 0 + 1 + 2 で 4 なら 0 + 1 + 2 + 3 の結果です

console.log(fn(1n))
// 0n
console.log(fn(2n))
// 1n
console.log(fn(3n))
// 3n
console.log(fn(4n))
// 6n
console.log(fn(5n))
// 10n
console.log(fn(6n))
// 15n
console.log(fn(7n))
// 21n
console.log(fn(8n))
// 28n

console.log(fn(1_000_000n))
// 499999500000n
console.log(fn(1_000_000_000n))
// 499999999500000000n
console.log(fn(1_000_000_000_000n))
// 499999999999500000000000n
console.log(fn(1_000_000_000_000_000n))
// 499999999999999500000000000000n
ildasm
dll ファイル調べたら やっぱり C++ で作ったものと .NET でつくったものは全く別ものみたい
同じ拡張子だから 同じように外部から使えるフォーマットかとちょっと期待したけど無理みたい
C++ で作った dll の中身を見るツールに C# で作ったものを入れても何も見れない状態でした

C# で作ったものの中身を見たいと思って調べたら ildasm というツールがあるみたい

コマンドラインツールのようですがダブルクリックで開くとウィンドウが出て GUI で使えました
dll を入れるとクラスやそのメソッドやプロパティなどを表示できます
さらに中間言語での処理を見ることもできました

C++ で作った dll を見るツールとは違いできることが多いです

また JetBrains の dotPeek というツールもあってこっちだと C# のコードまで見れました
本来のソースコードが入ってるわけではないので完全ではないですが 問題なく読める部分が多かったです
IL って思った以上に多くの情報を持ってるのですね

ところで ildasm は .NET Framework 専用で .NET Core にはついてきませんでした
ildasm は .NET Framework の SDK についてくるので VisualStudio を入れてると一緒に入ってるかと思います
場所はこのへん

C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.1 Tools

v10.0A は Windows のバージョンで 7.0A や v8.1A などもあります
NETFX の後の数字は .NET Framework のバージョンです

一応 .NET Core でも非公式なものでパッケージをインストールすることで使えるものはありました
試してないのでクオリティは不明です
esbuild
https://itnews.org/news_contents/oss-esbuild

Go 製で速いらしい
そういえば昔あった Rust 製の JavaScript バンドラーってどうなったんだっけ

比較はキャッシュなしみたいだけど 実際はキャッシュ使うのが当たり前だし スピードが必要な開発中は基本 watch してて更新時に差分だけ置き換えるものだから Webpack や Parcel の速度で困ることはそうそうないと思う

あと Parcel でた頃は設定とか面倒なのしたくないし速いほうがいいしと Parcel 使ってたけど設定できることが少なくて結局 Webpack がメインになったので速度よりも拡張性があるほうがいいな
これは見た感じ速度追求系ぽいけどそのへんどうなんだろう
なんだかんだ短くかけるのは jQuery
ちょっとした事情でコードを短く書きたいときがありました
cdn をロードできるものはその部分は数えません

react や lit-html などは表示したいデータを持ってる場合は便利ですが そうでもない場合は DOM と二重で持って管理することになりますし ライブラリ都合で書かないといけない部分も多々あります
SPA みたいな規模が大きいものでもなく ちょっとしたページなら DOM API だけ使って書いたほうが短く書けます

とは言っても WebComponents にしてしまうとクラス定義とかでてきて書く量が増えます
コンポーネントに分割できて考えやすい部分はありますが 短く書くのには向いてません
昔ながらの querySelector とプロパティの更新が基本になります

そうなると思うのが querySelector とか textContent とか長いのですよね
コードが長めのものだと $ に document.querySelector を割り当てたりしてますが その処理自体を書くことになります

その結果ライブラリの中身を気にせず自分のコードだけを小さくしたいなら jQuery が一番短くかけるのですよね
$ や text や html など DOM API だと長いプロパティ名やメソッド名を短くしていて メソッドチェーン化することで代入や呼び出しの対象を毎回書かなくて済むようにされています

もうほぼ使うこともないと思いましたが 1 つの HTML ファイルに全てまとめた上でファイルサイズをできる限り小さくしたいという状況だと役立ちました
CSS Modules で別モジュールのクラスを使いたい
便利だけど別のモジュールのクラスを使えない
例えばこういう CSS

.readonly .edit {
display: none;
}

.edit がこのモジュールのクラスで .readonly はモジュールの外で指定される場合
別クラスの .readonly であることを書くすべがないので実現できない

使用例

<user-list class="readonly">
<user-item>
<div>namae</div>
<div>
<button class="edit"></button>
</div>
</user-item>
<user-item>...</user-item>
<user-item>...</user-item>
<user-item>...</user-item>
</user-list>

user-list に .readonly をつけたら中の user-item 全部で .edit を消したい

stackoverflow とか調べてみると 親のクラスを使わずそのコンポーネントにクラスを指定すべきというのが出てくる
この例で言うと全部の user-item に .readonly つける
ムダが多くて気がすすまないけどコンポーネント的には自分自身にオプションが設定されてるのが正しいのだとか
わかるといえばわかるけどやりたくない
WebComponents 自体 :host-context() でホストより外側のセレクタ使えるし

readonly が user-list より上の page-user みたいな要素についてる場合も許可するのなら いっそ モジュールで一意なクラスに変換しないのもあり
:global を使ってクラスにするか CSS Modules の変換対処外の属性を使ったセレクタにするか ([data-readonly] みたいなの)
readonly みたいなのだと良さそうだけどものによっては別の意味のセレクタが意図せず重複もありそう

親が子を把握してるのなら user-list が user-item の CSS をインポートして親側に子のセレクタをつけるのもあり
ただやりすぎるとすごく複雑になってきそうだし 別コンポーネント用の CSS Modules を使うのは控えめのほうがいいかも
Parcel で CSS Modules だけ設定が違う理由
深く考えてなかったけど Parcel で CSS Modules だけプラグイン設定方法が他と違ってる

{
"modules": true,
"plugins": {
"autoprefixer": {
"grid": true
}
}
}

https://parceljs.org/css.html

ドキュメントだとオブジェクトをエクスポートするので特別な対応が必要と書いてる

モジュールを有効にして以下のコードをバンドルする

.foo{}
.bar{}
import styles from "./test.css"
console.log(styles)
parcel build --no-minify index.js
結果は
/*略*/
})({"qP9o":[function(require,module,exports) {
module.exports = {
"foo": "_foo_05711",
"bar": "_bar_05711"
};
},{}],"Focm":[function(require,module,exports) {
"use strict";

var _test = _interopRequireDefault(require("./test.css"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

console.log(_test.default);
},{"./test.css":"qP9o"}]},{},["Focm"], null)
//# sourceMappingURL=/index.js.map

クラス名のオブジェクトがエクスポートされてる

モジュールが無効だとこう
/* 略 */
})({"qP9o":[function(require,module,exports) {

},{}],"Focm":[function(require,module,exports) {
/* 略 */

処理は何もなし
エクスポート内容が無いときも空オブジェクトで常にエクスポートがあるなら共通でも良さそうだけど モジュールがあるときだけ追加の処理でエクスポートしてそう
Parcel 内部でその判断するためにフラグ形式でモジュールを使うかどうか判断必要みたい

エクスポートの必要性
モジュール使わないときは出力される CSS はそのままのクラス名
JavaScript 側での処理はいらずに HTML や JavaScript では CSS ファイルに書いたままのクラス名を書くだけ
モジュール使うときは一意な名前に変換されてる
その変換後の名前を知るために JavaScript では CSS をインポートして元のクラス名から変換後のクラス名を取得して DOM に設定する
systemctl status が less で開かれる
久々に systemctl status でデーモンの状態を見たら less で開かれるようになってました
これまでは普通に status のテキストが出力されていましたが less で status のテキスト部分だけが開かれた挙動になってました

less なので検索できたり 画面右端ではみ出た部分も右にスクロールさせて読めます
これまでは詳細みるなら -l (?) みたいなオプションを追加してとか言われて面倒だったのが不要になったようです
ただ一々画面が切り替わったり 上の方にスクロールしてログとしてあとから確認できないなどのデメリットもあります

変わったのは fedora を 31 にアップデートしてからの気がします
less で見たいならパイプすればよくて 基本はこれまでのように単純に出力でいいかなと思って戻す方法がないか調べたらこんなページがありました

https://unix.stackexchange.com/questions/343168/can-i-prevent-service-foo-status-from-paging-its-output-through-less

--no-pager オプションを使えばいいようです
未使用 CSS を削除するツール
たまにネットで見かけますが 個人的にはあまり信用してません
必要なところまで消されそうな気がして仕方ないです

CSS はクラスや属性名で指定できますが それらは静的なものとは限らないです
JavaScript から作られるものも多くあるわけですが 文字列結合など色々処理した結果できあがる文字列の場合もあります
不要部分を削除してしまうわけですから 多分使われてなさそう 程度で消すと動かなくなって重大な問題です

静的な解析だと限界がありますし 実際に動かして使われたかを判別する機能は Chrome の devtools についてます
ただそれも 実際にそのスタイルが使用される状態になる必要があります
一通りの操作はしてみても 特別な状態の組み合わせでしか起きないスタイルの指定があるかもしれません
すべての状態の組み合わせで試すなんて規模が大きいと無理がありますし CSS や HTML の書き方や JavaScript でクラスの指定など何らかのルールに従って書いてる前提でもないと確実にないって言い切るのはかなり難しいと思います

ただ 実際に使う操作を試して使っていないスタイルなら 特別な組み合わせでのみ使用されるケースがあってもとりあえず削除してもいいのかもしれません

作った側は使うと確実にバグが発生するのを認識していて 修正依頼が来たら修正する準備はできているのに 誰も使わない機能なせいで数年前からその状態のままという話を聞いたことがあります
業務で使うようなシステムになるとユーザ数も限られて割とあるのだとか
それに似た話で テストをするのが作った側ではなく 使う側がやることで 機能上できはするものの実際には使われないような使い方はバグがあっても気づかれず放置で 逆によく使う使い方は丁寧にチェックされるというやり方をしてるところもあるようです
誰も使わない機能や使い方でのバグを直しても時間の無駄ですし 使う側としては使う機能だけちゃんと動いてくれればいいですからね
バグが絶対許されない環境でもないならそれくらいのゆるさのほうが効率も良くていいのかもしれません
HTTPS は強要するものじゃなくて住み分けるものです
こんな記事が
https://www.itmedia.co.jp/news/articles/2002/20/news059.html

必要以上に HTTPS を強要してくる最近の風潮はホント迷惑ですよね
まぁこの場合は Teams はログイン必要なサービスでプライベートな情報を保存するので HTTPS が必須なサービスなわけで Google が HTTPS HTTPS 言ってなくても起きた問題ですけど

Microsoft くらいでもミスがあるようなものですし めんどくさく大変なものです
セキュリティはめんどくさくなるようするものだとかいう話もあるくらいですし

本当に HTTPS が必要なサービスは HTTPS を使うべきですけど必要ないところまで HTTPS 化させようという仕組みが多いです
Google のランキングに影響だとか JavaScript で使える機能が制限だとか HTTPS を必要以上に優遇して HTTP の使いづらくしてます
HTTP で十分なものまで HTTPS にしようとしてるのが気に入らないです
余計なものがなくてシンプルなテキストの HTTP だからこそいい部分も多いはずです

HTTPS だと証明書も必要ですし ウェブサーバを立てる難易度が上がって個人レベルで立てづらくなります
静的ファイルをホストするだけなら無料サービスも多いですが サーバサイドもとなると無料はほとんどないですし
SNS みたいなところにまとまるよりは 自由な個人サイトみたいなのが多いほうが好きなので 気軽にサーバを立てづらくなるようなものはやめてほしいものです
async 対応なコレクションメソッドがほしい
map は普通に map に渡す関数を async にしたら Promise の配列になるので Promise.all するだけ

const items = [10, 20, 30]
const asyncDiv5 = num => new Promise(resolve => setTimeout(resolve, 100, num / 5))

await Promise.all(items.map(asyncDiv5))
// [2, 4, 6]

reduce も返り値が Promise でも次の関数に渡されるのが Promise なだけだから次の関数が前回の値を await して使えばいい

const values = [1, 2, 3, 4]
const getValue = x => Promise.resolve(x * 10)

await values.reduce(async (a, b) => (await a) + (await getValue(b)), 0)
// 100

問題は渡した関数の返り値の値をコレクションメソッド内部で扱う場合
これらは Promise に対応してないので Promise を解決せずそのまま Promise 自体を結果として扱う
なので filter の場合だと Promise オブジェクトはオブジェクトなので true になって全部が残るし find でも最初のが絶対マッチする

console.log([1, 2].filter(async x => false))
// [1, 2]

console.log([1, 2].find(async x => false))
// 1

filter に対応するならこういう一度 Promise の中身を取り出す処理が必要になる

const filter = async (arr, fn) => {
const filter_flags = await Promise.all(items.map(fn))
return arr.filter((_, i) => filter_flags[i])
}

この処理を毎回直接書くのは避けたいくらいので filter 関数を自作することになる
標準で用意してくれればいいのに

const items = [0, 1, 2, 3, 4]
const fn = x => {
if(x === 0) return false
if(x === 1) return true
if(x === 2) return new Promise(r => setTimeout(r, 1000, true))
if(x === 3) return Promise.resolve(false)
if(x === 4) return Promise.resolve(true)
}

await filter(items, fn)
// [1, 2, 4]
Twitter のツイート数取得
ニュース系サイトで Twitter でのツイート数が表示されてるのを見かけました
ツイート数ってどうやってとれるんだろう?と思ったのでソースを見てみたら JavaScript で取得していました
Twitter の API かなと思ったら https://jsoon.digitiminimi.com/ のサイトでした

見てみたらツイート数を取得するサービスをやってるようです
わざわざこういうのを使ってるあたり Twitter 自体にはツイート数取得の機能はなさそうですね
Safari は回転制御できない
こんな機能見つけました
https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock

モバイル端末の回転を制御できるようです
ゲームなど一部のアプリだと縦長か横長どっちかの表示のみだったりします
でも Web だとそれができなくて不便です
viewport 固定で横長専用とかしたいのですけど

それがこれをつかえばできる!と思ってました
でも Safari (iOS) は非対応でした
モバイル端末考えると iOS シェアは多いですし Android だけできてもなぁという気分です

これに限らず Safari って独自の使用があったり変な動きしたりと扱いづらいです
新機能の実装も Firefox のほうが早いことが多くて全部で動くものとなると Safari がネックになってることも多いです

Win7 のサポートが終わって IE 対応がほぼなくなると Safari が第二の IE になるようにしか思えません……
一番の問題は iOS で Chrome など別のブラウザ入れてもエンジンは Safari の Webkit 固定なんですよね
Go → Rust てよくみるよね
Discord も Go → Rust に切り替えたらしいです

https://blog.discordapp.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f

けっこうこの移行よくみかけますね
最近だとネイティブにビルドできるメジャーなものといえばだいたいこの 2 つだからかな

C/C++ は複雑で避けられがちですし D はまだ生きてたのって感じですし
.NET 系は Core は Linux などで動くとはいってもネイティブとはちょっと違いますし
同じく Java 系も

個人的には Go は興味なくて Rust は興味あるので Rust に移行するプロダクトが多いのは嬉しいことです

そういえば deno も当初は Go で実装していて どうして Rust にしないの? みたいなこと言われて Rust にしたんでしたっけ
そんな deno も予定では 2 月末に 1.0 でるらしいです
完全 Web 互換らしいのでリリースしたら使ってみようかと期待してます
ツリー構造の要素をひとつずつ返してくれるジェネレータ
function* treeIter(root) {
yield root
for(const child of root.children || []) {
yield* treeIter(child)
}
}
const tree = {
name: "root",
children: [
{
name: "item1",
children: [
{
name: "11",
children: [
{
name: "111",
children: [],
}
],
},
{
name: "12",
children: [],
},
{
name: "13",
children: [],
}
],
},
{
name: "item2",
children: [
{
name: "21",
children: [],
}
],
},
],
}

Array.from(treeIter(tree), x => x.name)
// ["root", "item1", "11", "111", "12", "13", "item2", "21"]

JavaScript でタプル
必要性はともかく変更不可版 Array ということでこれでよさそう
中身同じでも等しいものにならないのが不便かも

class Tuple extends Array {
constructor(...a) {
super()
this.push(...a)
Object.freeze(this)
}
}

作ったタプルをすべて保存しておいて同じ中身なら既存のを返せばできそうだけどメモリ的につらそう
WeakSet を forEach できたらいいのに
JSON 比較
JSON を比較したいとき文字列比較だと オブジェクトの順番の違いでも違うもの扱いされる
オブジェクトや配列を再帰的にチェックしていくのは面倒
片方のプロパティ全部をもう片方と全部比較しても もう片方のほうにしか無いプロパティもあったり 考慮することが意外とあってコードも長くなる

短く書きたかったので オブジェクトは Object.entries の形式化してソートするだけ
比較は JSON.stringify した文字列比較に任せる方針なもの作ってみた

const rec = v =>
(v instanceof Object && !Array.isArray(v)) ?
Object.entries(v).map(x => [x[0], rec(x[1])]).sort((a, b) => a[0].localeCompare(b[0]))
:
v

const jsonDiff = (a, b) =>
JSON.stringify(rec(a)) === JSON.stringify(rec(b))

jsonDiff({a: 1, b: 2}, {b: 2, a: 1})
// true

JSON.stringify({a: 1, b: 2}) === JSON.stringify({b: 2, a: 1})
// false

JSON を比較するくらい標準機能にあってもいいと思うのに
SQL で列名が被って困る
SQL の列名は同じ種類の ID なら同じ名前にしておけば USING(xx_id) で JOIN できたり便利なので 列名を一意にしようなんて思ったことはありませんでした

しかし 「SELECT * FROM ~」 のように全取得してると LEFT JOIN で JOIN 先にマッチする行がないと id が null になってしまう問題に困りました
同じ列名なのでオブジェクトや連想配列やディクショナリとして取得するとあとの方の null で上書きされてしまうのですよね
「*」 を使わず全部書けば解決ですが 長いです
ワイルドカードで除外が選べれば助かるケースはかなりあるのですが SQL では対応してません
それに SQL って全然更新されないので JavaScript などのように待てば便利なる期待もありません
せめて 「select a.* as a__*」 で a__ プレフィックスつけてくれるみたいなのができたらよかったのですけど

それで思ったのが最初から列名を 「tablename__columnname」 みたいなのにしておくことです
見た目はいまいちですが JOIN が入ってくると列名が被る可能性があって 結局 WHERE や SELECT で 「tablename.columnname」 のようにテーブル名も含めて書くならあんまり変わりません
とはいえやっぱり長いし 実際に 「tablename.columnname」 と書くときはエイリアス使って 1, 2 文字のテーブル名です
なのでエイリアスを含めた 「tablealias__columnname」 にしておくのはありな気がしました
列名指定のためのエイリアスが不要になりますし

CREATE TABLE foo (
f__id integer,
f__name text,
PRIMARY KEY (f__id)
);
CREATE TABLE bar (
b__id integer,
b__name text,
b__f_id integer,
PRIMARY KEY (b__id)
);

SELECT * FROM foo LEFT JOIN bar ON f__id = b__f_id WHERE f__id < 10;
JavaScript int max
// signed int32 max
-1 >>> 1
// 2147483647

// unsigned int32 max
-1 >>> 0
// 4294967295

// number max
Number.MAX_SAFE_INTEGER
// 9007199254740991
サーバ使えない環境で proxy
長いクエリがある URL に短縮 URL を作って リダイレクトせず短縮 URL のまま表示する
サーバサイドも使えれば長い URL のページへ proxy するだけで済むので単純
静的ファイルのみしか使えない場合はどうしようかと考えたら全画面 iframe 使うだけだった

<!doctype html>

<style>
body { margin: 0; }
iframe {
display: block;
width: 100vw;
height: 100vh;
border: 0;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
<iframe src="page.html"></iframe>

src の page.html のところに長い URL を設定する
iframe だけのページを iframe の URL 変えながらたくさん作るのも面倒なのでマッピングのデータの json をロードして今のページに対する長い URL を動的に作るほうがいいかも
ページ数分の大きめな json を毎回ロードすることになるけど キャッシュされればそこまで困るほどでもなさそう

JSONP ふうに iframe への設定も含めとくとか

!function(values) {
document.querySelector("iframe").src = values[location.pathname]
}({
"/azj4": "/foo/bar.html?longlonglong=query",
"/bj9c": "/long-url.html",
// ...
// ....
})
Chrome でたまにあるアップデートできない現象
何が悪いんだろう?

chrome://settings/help

でアップデートありになってアップデート完了して再起動ボタン押したのに同じバージョンで起動される
一度起きると何回繰り返しても一緒
手動再起動で Chrome を終了して Chrome のプロセスがないのを確認してから再起動してもだめ
タスクスケジューラから GoogleUpdate を手動実行してもだめ

とりあえず new_chrome.exe 使えば新しいバージョンを使えるけど 普通に起動していようにアップデート完了させたい

C:\Program Files (x86)\Google\Chrome\Application\new_chrome.exe
Twitter で見かけた筆算の問題を力技でやってみた
話題になっててまとめられてたツイートでこんなのがありました
https://twitter.com/aty_carbuncle/status/1224323674372657156

うーむ 難しそうですね
考えるのが面倒になってきますね

……総当りでやればいいや

const f = (a, b) => {
const s = String(a * 10 / b)
if(!(s.length === 3 && s[2] !== "0")) return
const [x, y, z] = Array.from(s, e => e * b)
if(!(x % 10 === 6 && String(x).length === 3 && String(y).length === 2 && String(z).length === 2)) return
const xx = ~~(a / 10) - x
if(!(String(xx).length === 2)) return
const yy = xx * 10 + (a % 10) - y
if(!(String(yy).length === 1)) return
return true
}
for(let i=1000;i<10000;i++){
for(let j=10;j<100;j++) {
f(i, j) && console.log(i, j, i/j)
}
}
1365  14  97.5

その場の勢いで雑につくったものなので変数名とかはテキトー
結果は無事正解でしたが ほんとにひとつしか当てはまるものがないんですねー
中1でこれはすごい
Chrome で表示されるインスタンスの型名
Chrome だと

const x = class {}
new x()
// x {}

のように型名が変数名から推測されて表示されます
プロパティ名を使えば変数名に使えない文字列も使えます

const tmp = {}
tmp["a123@*+<>%$#ABC"] = class {}
const c = tmp["a123@*+<>%$#ABC"]
new c()
// tmp.a123@*+<>%$#ABC {}

オブジェクトの名前の tmp も入ってしまいますが結構便利です
やりたいことは動的に名前をつけることで いざやってみると

const tmp = {}
const random = "c" + ~~(Math.random() * 100)
tmp[random] = class {}
const c = tmp[random]
new c()
// tmp.<computed> {}

静的に判断しているようで変数になっていればすべて <computed> になりました

この機能を活かせるところは少なそうです
そもそも Chrome のみで Firefox では全部 Object 表示なので そこまで積極的に使っていくべきとも言えないです
オーバーロード的なことするときの書き方
こういう関数があります

const fn = (target) => {
if (!target) {
for (const item of getAll()) {
something(item)
}
} else {
something(target)
}
}

引数 target が指定されていたらそれを something 関数に渡します
指定されてなければ getAll で全部を取得した上で for 文で全部を something に渡します

引数があればそれを なければ全部を対象になにかの処理をするというものです

something 関数程度ならこれでいいのですが something が長くなってくると同じものを 2 箇所に書きたくないです
同じものを 2 回書きたくないなら関数にまとめてしまうのが簡単です

const fn = (target) => {
const f = (arg) => { something(arg) }
if (!target) {
for (const item of getAll()) {
f(item)
}
} else {
f(target)
}
}

シンプルなもののはずなのに内部に関数もあったりでごちゃごちゃしてきた感じがします
毎回 1 回余分に関数呼び出しも入りますし もうちょっと別の方法を考えたいです

関数呼び出しを使わない方針で考えると something 部分は固定でそれより前に処理する対象を 1 つの変数に入れておくと場合分けがあっても 1 つの記述で済みます
今回は一方では for 文で複数回実行するので
for 文の中に書く前提で target が渡されたらそれ単体の配列にします

const fn = (target) => {
const targets = target ? [target] : getAll()
for (const t of targets) {
something(t)
}
}

短くなりましたが target 指定のほうがメイン(の想定)なのにわざわざ配列化するのは無駄な感じがします
それに本来この関数がやりたい something が for の中で常にループするのでやりたいことがパット見分かりづらい感じもします
作り的にはオーバーロードにあたるもので その機能がある言語でのやり方を考えてみます
それらは別々の関数になっていて 引数なし版では for 文の中で引数あり版の関数を呼び出すはずです
その考え方でやってみると

const fn = (target) => {
if (!target) {
for (const item of getAll()) {
fn(item)
}
return
}
something(target)
}

忘れがちな return があったりさっきのより長くなってるのが気になりますが 一番アリかなって気もします
前半後半で分けて見ると 前半は引数チェック的なもので この関数で本来やりたいことじゃない部分
後半が本来やりたい部分で something に引数の target を入れて実行となってます

再帰関数呼び出ししてるので 1 つ前のコードではなくした関数呼び出しをしてしまってますが その関数がやりたいコードを直接実行するようにして それより前に例外的な場合は引数修正して再実行という考え方がしっくり来ました
その関数がやりたいことが for の中やローカル関数内に押し込められるとやりたいことがわかりづらくなりますからね