MathJaxをデバッグしてJavaScriptの理解を深める
概要
JavaScriptで書かれたMathJaxライブラリは、TeXのような組版処理をサービスを提供しているCDN(Content Delivery Network:コンテンツ配信サービス)あるいは自前のサーバーに配置するかするようにして構築するものです。主に数式の組版をするために提供されているサービスです。
このような組版処理はいくらやってもらってもいいという感じで、楽譜とかも組版出来たらいいのにと夢みたいなことをおもっていたのですが、一部には実際に楽譜が組めるようになっているサービスもあるようですが、なっとくいかない仕上がりです。納得しろやオマエ。って思うでしょ。そうなんすよ。作れないくせになっとくしてないんすよ。もっとやりたいことは簡単な楽譜処理なんすよ。そういうのはおいといて、数式の組版を実現したMathJaxはスゴイと思います。それで、これを理解したら自分にも役に立つJavaScriptが作れるようになるんじゃないかと思ったりしました。JavaScript初心者ですよ。
MathJaxに使われている技術を理解してく記事です。そして理解するための工夫や解析によってわかったMathJaxの考え方をここで書いていきます。自分が使ったことのあるのはMathJaxの中の/es5/tex-mml-chtml.jsで、これをちょろっと除くとまぁエグイ。一行目で終わってるプログラム。さすが、一行の長さがエグイ。インデントしてみたら5万行にもわたるプログラムが1行になってる。改行なしのプログラムあるんだなぁ。
まずは、インデント処理を自動でやってくれるサービスと出会うことから始めました。
いろいろなプログラムを自動整形するサービス
MathJaxを理解する作業をはじめて、いきなりありがたいサービスにまた出会う。このサービスのプログラムもすごいね。完璧すぎる自動整形インデント処理をしてくれます。そのJavaScriptの自動整形サイトが以下です。
- Online Javascript Beautifier - BeautifyConverter.com
他にもBeautifier Minifier/CSV/Excel/TSV/HTML/JSON/SQL/XML/YAML/Validators/CSS/Gen/Unit/Escape/IMG/PDF/IP/Color/Othersという整形処理ができる。自分で作ったプログラムが画期的である場合にはこのような自動整形処理を他人に任せるのは知的財産の流出の危険があるので、気を付けてください。信頼できるサイトもあるかもしれませんが、自分は知りません。サービス自体はありがたい。Microsoftがこういう機能をVisualStudioCodeにつけていたら楽だったのにな。あるっちゃあるんすよ。Shift+Alt+Fらしい。あまり自動整形されないっす。
とはいいつつも自動整形が必要なのはここまでヒドイと思ったプログラムだけですけどね。自分でプログラム作成して整形したものが最高に美しい。余計なことをするのがMicrosoftのエディタって感じですけど、Microsoftの考え方と共鳴しながらのコーディングをして、美しさを求めるのが自分流。MathJaxを自動整形して見えてくるものはある。最初の方に関数が連想配列でつめこまれて1000から3000くらいの関数が配列化されている。しかも番号だけで管理している。手ごわい。いみわからん。まったくいみわからん。変数名も1文字が多い。意味わからん。そんなことできるの?ってぐらいスゴイ。なんかそういう風にプログラムを意味わからんくする自動ツールがあるのかもしれん。でも自動整形したら少しましになった。あー、ありましたねminifyとかってサービスこれのことかな。意味のあるプログラム変数名を圧縮してしまう技。こういうのを使ってるのかもしれない。でもソースで配布してるのおかしくね。MathJaxの中の人。ちがうのか。謎のままおいておこう。
デバッグ環境を整える
基本的にはVScodeで簡易WebServerの元でデバッグで記述した方法によってVSCodeでデバッグします。ソースのダウンロードにはGitコマンドっていうのを使いたくて、Git for Windowsみたいなのをインストールしました。Gitのインストーラーがややこしい。Ver2.38.1ですが、CommandPromptでGitコマンドが使えりゃいいかなと思ったりするだけなんですけど、ややこしい。基本デフォルト設定でインストールするだけかなと思ったんですけどところどころ触ってやらないとCommandPromptで使えるような状態にはならないらしい。インストーラはhttps://gitforwindows.org/からデカデカとあるDownloadから入手。手を加えたところを太字にするとして、おおまかな流れは
実行→アプリがデバイスに変更[はい]→ライセンス確認[I Agree]→インストール先[Next]→フォルダ作成確認[はい]→
インストールオプション[Next](右クリックメニューにGitShell起動とGitBash起動を追加/大きいファイルサポート/*.gitファイルをテキストエディタで編集/*.shファイルをGitBashで起動)→スタートメニューのグループ名(GITのまま)[Next]→コミットメッセージで使うエディタは何[Use Vim(the ubiquitous text editor) as Git's default editor]-[Next]→Git initで作られるブランチ名(master (Let Git Decide:Gitに決定させよう))[Next]→パスの設定[Git from the command line and also from 3rd-party software(path追加Gitインストール先\Git\cmd)]-[Next]→OpenSSHのインストール[Use bundled OpenSSH]-[Next]→HTTPSリモートリポジトリ接続[Use the OpenSSL library]-[Next]→改行コード自動変換[Checkout Windows-style,commit Unix-style line endings(コミット処理でなんかうまくいかないときはこの設定が邪魔していることも覚えておかないといけませんよ。あまり使わない機能なので大丈夫だと思いますけど)]-[Next]→Git Bashターミナルを選択[Use MinTTY]-[Next]→Git pullの設定[Default(git pull --ff)]-[Next]→Credentioal設定[Git CredentialManager]-[Next]→オプション[Enable file system caching のみ ON]-[Next]→試験運用オプション[check無し]-[Install]
あらゆるプロジェクトにおいて、GitHubでソースコードを管理する波は来ています。確実に。Gitコマンドつかえるようになったほうが良いと思います。GitHubの一人勝ちだな。一般向けに最初に納得いくものを作った人たち偉い。会社には会社の中のコード管理があると思います。Visual Source Safeなつかしい。そんなのつかっているひといるのかな。ソース管理とかしたことないからわからないことばかりだけど、必要だよね。
例えばC:¥JavaScriptフォルダを作って、そこにソースをダウンロードする場合。
cd C:¥JavaScript
git clone git://github.com/mathjax/MathJax.git MathJax
これだけでC:¥JavaScript¥MathJaxが出来て、その中にes5フォルダが出来上がります。es5とはEcmaScriptというJavaScriptのもう一つの規格名がありまして、これにしたがっているのがes5です。何がどう違うかは自分は完全には理解していません。これに対応している関数や配列なんかには __esModule= true という値が取得できるようになっていたりします。高度なJavaScriptではこの値を制御するみたいな記事もあります。自分はまだ理解していません。
いろいろな種類の動作を確認するサンプルもダウンロードしましょう。MathJaxの多くの機能を網羅するようなSampleってのはありがたいものです。以下のアドレスから取得できます。
同じフォルダ(例C:\JavaScript\MathJax)にDownloadしましょう。結果的にC:\JavaScript\MathJax\MathJax-Example\MathJax-base\index.htmlのようなものにアクセスできるようになります。このindex.htmlには2次方程式の解の公式がサンプル表示されるようになっています。Mathjaxのプログラムの参照部分が ../MathJax.js になっているので、 ../../es5/tex-mml-chtml.js のように書き換える必要があります。全部のファイルで書き換えないとだめなのでちょっと辛いですけど、やってみましょう。ファイルによっては違うプログラムを参照した方がいいようなものもあります。これで関連記事のようなVSCodeを設定をするとデバッグができるようになります。
軽く追いかけてみる
序盤その1
自動整形で変換したtex-mml-chtml.jsの1行目の (function(){ にブレークポイントを設定して、プライマリサイドバーの上から4つめ実行とデバッグを選択して、launch.jsonを作ったら、Open index.html の横にある 蛍光色黄緑 ▷ のボタンを押します。ブラウザが起動して、VisualStudioCodeのtex-mml-chtml.jsの1行目で止まります。
最初の行に"use strict";とあるので、このプログラムでは、強制的に構文チェックをするモードになり、変数定義を正式に実施していないとエラーになるモードになります。
次に __webpack_modules__ 代入処理で配列が定義されます。 {351 : … とあるので、351が最初に定義される関数みたいですね。何に使うものなのか、この番号からはあまり想像つきません。ものすごい数の配列になってそう。__webpack_modules__はいわば、関数群ですね。
次に __webpack_module_cache__ = {}; という上記関数群のためのcacheと思われる変数への初期化がされます。プログラムが進むとここにいろいろ設定されていくのでしょう。よく使うやつとかがこんなかにはいるのかな。__webpack_modules__はものスゴイ数の関数がありますので。
次に function __webpack_require__(t){ … } があるので、tという変数の引数を受け取る__webpack_require__関数が定義されています。短いです。
function __webpack_require__(t) {
var e = __webpack_module_cache__[t];
if(void 0 !== e) return e.exports;
var r = __webpack_module_cache__[t] = {
exports: {}
};
return __webpack_modules__[t].call(r.exports, r, r.exports, __webpack_require__), r.exports
}
ペロッと貼っておきました。cacheの中に設定されている連想配列キー変数 t の配列値を e に取得して何もなければ t の配列値にexports : {} という連想配列を代入して、その値を更に r で覚えさせておくみたいだね。そして、最初に登場にした巨大な関数群を格納している配列 t を実行しています。 返却する値として .call は連想配列値を実行ですね。連想配列にプログラムを格納しておくという技なんだな。なるほど。その引数は、たった今、{exports:{}}とした r の exports キーの値 {} と r 全体 と また同じ、r の exports キーの値 {} と この関数全体の値 __webpack_require__ も引数にしていて4つが引数になっています。この関数群の中のひとつの実行結果が返り値の一つ目、そしてもうひとつ何回も登場するr の exports キーの値 {} を返却するみたい。
次に__webpack_require__に.gというメンバ変数をつくって、これに何やら設定する関数が実行されます。
__webpack_require__.g = function() {
if("object" == typeof globalThis) return globalThis;
try {
return this || new Function("return this")()
} catch(t) {
if("object" == typeof window) return window
}
}();
ここは単純だな。globalThisという値を __webpack_require__.g に代入する処理なんだけど、ちゃんとobjectとして存在しているかを確認して代入している慎重さがある。globalThisというオブジェクトが無い場合は例外処理付の次の処理を実施します。tryはエラーが発生する可能性がある処理で、エラーが発生したらcatchの処理をするという感じです。返却される可能性のある値は、this || new Function("return this")() エラーになった場合は、window ですね。とにかく取得できる環境変数は取るみたいな処理ですね。catch(t)のtはエラー情報格納変数です。eを使う人も多い印象だけど、tでもいいんだね。
勉強になるのは this || new Function("return this")() っていう部分が無駄に感じるけど、Debugしてみると単純なthisはundefinedで、new Function("return this")()だとwindowオブジェクトがかえってきたりして、意味が違うんだなって思ったことです。そして、この場合の || の使い方がむずい。なんじゃコレ。論理和演算だからどっちかがtrueになったらtrueが返却され、両方がfalseならfalseがかえるのだろう。それも動かないときはwindowオブジェクトで扱う。
まだわからないのは
- new Function("return this")()の後ろのカッコの有り無しの違い
- 関数構文の中のthisとfunction(){}の中のthisの違い。
また今度だな。
序盤その2
次にvar __webpack_exports__ = {}; で __webpack_exports__ の連想配列変数を初期化。
次はちょっと特殊 !function(){}という関数の実行処理です。戻り値のBool値が反転しそうだ。論理否定付きの関数。こんなこともできるんだな。なるほどなるほど。function xxx = {} や var xxx = { zzz : function(x,x,x) = {} }なら関数定義だけfunction(){ }なら実行する内容になるんだね。定義だけか関数だよといいながらも即実行。
次の部分からは __webpack_require__(t 【←数値】 )で5つの値 t, e, r, n, o を定義。なんの処理の関数を結び付けるのやら、みてもわからんだろうな。9515, 3282, 235, 265, 2388 暗号だな。さっきしらべたとおり __webpack_require__(t) を呼ぶと、__webpack_modules__[t].call(xx,xx,xx,xx)が実行される。__webpack_modules_cache__[t]には{ exports:{ } }が作成されている状態です。
何やってるか、想像がつきそうなのが2個3個あればいいな。
__webpack_modules__[9515].call(r.exports, r, r.exports, __webpack_require__)
9515: function(t, e, r) {
var n = this && this.__values || function(t) {
var e = "function" == typeof Symbol && Symbol.iterator,
r = e && t[e],
n = 0;
if(r) return r.call(t);
if(t && "number" == typeof t.length) return {
next: function() {
return t && n >= t.length && (t = void 0), {
value: t && t[n++],
done: !t
}
}
};
throw new TypeError(e ? "Object is not iterable." : "Symbol.iterator is not defined.")
};
Object.defineProperty(e, "__esModule", {
value: !0
}), e.MathJax = e.combineWithMathJax = e.combineDefaults = e.combineConfig = e.isObject = void 0;
var o = r(3282);
function i(t) {
return "object" == typeof t && null !== t
}
function s(t, e) {
var r, o;
try {
for(var a = n(Object.keys(e)), l = a.next(); !l.done; l = a.next()) {
var c = l.value;
"__esModule" !== c && (!i(t[c]) || !i(e[c]) || e[c] instanceof Promise ? null !== e[c] && void 0 !== e[c] && (t[c] = e[c]) : s(t[c], e[c]))
}
} catch(t) {
r = {
error: t
}
} finally {
try {
l && !l.done && (o = a.return) && o.call(a)
} finally {
if(r) throw r.error
}
}
return t
}
e.isObject = i, e.combineConfig = s, e.combineDefaults = function t(e, r, o) {
var s, a;
e[r] || (e[r] = {}), e = e[r];
try {
for(var l = n(Object.keys(o)), c = l.next(); !c.done; c = l.next()) {
var u = c.value;
i(e[u]) && i(o[u]) ? t(e, u, o[u]) : null == e[u] && null != o[u] && (e[u] = o[u])
}
} catch(t) {
s = {
error: t
}
} finally {
try {
c && !c.done && (a = l.return) && a.call(l)
} finally {
if(s) throw s.error
}
}
return e
}, e.combineWithMathJax = function(t) {
return s(e.MathJax, t)
}, void 0 === r.g.MathJax && (r.g.MathJax = {}), r.g.MathJax.version || (r.g.MathJax = {
version: o.VERSION,
_: {},
config: r.g.MathJax
}), e.MathJax = r.g.MathJax
},
なかなかわけわからん。
var n = this && this.__values || function(t){…}
グローバルオブジェクトだからthisはWindowオブジェクトなんだけど、strictモードなので、. の前が省略されているので、undefined だね。だから、値だけを取り出す、this.__values も undefined。n は function(t) があるから true かな。論理演算している意味が謎だわ。何がしたいんだろう。ま、あとあと何回か呼び出されるんだろうと思って、ブレークポイントを設定したら、謎のコードが33回呼ばれる。おいかけきれるかこれ? t には何かのキーワードみたいなのが入って呼ばれるね。呼び出されるときの t の値を記録してみるか。
1回目 (10) ['paths', 'source', 'dependencies', 'provides', 'load', 'ready', 'failed', 'require', 'pathFilters', 'versionWarnings'] 2回目 ( 1) ['loader'] 3回目 ( 9) ['input', 'output', 'handler', 'adaptor', 'document', 'elements', 'typeset', 'ready', 'pageReady'] 4回目 ( 2) ['startup', 'options'] 5回目 ( 2) ['startup', 'options'] 6回目 (1) ['_'] 7回目 (1) ['components'] 8回目 (37) ['a11y/semantic-enrich', 'a11y/complexity', 'a11y/explorer', '[mml]/mml3', '[tex]/all-packages', '[tex]/action', '[tex]/autoload', '[tex]/ams', '[tex]/amscd', '[tex]/bbox', '[tex]/boldsymbol', '[tex]/braket', '[tex]/bussproofs', '[tex]/cancel', '[tex]/centernot', '[tex]/color', '[tex]/colorv2', '[tex]/colortbl', '[tex]/configmacros', '[tex]/enclose', '[tex]/extpfeil', '[tex]/html', '[tex]/mathtools', '[tex]/mhchem', '[tex]/newcommand', '[tex]/noerrors', '[tex]/noundefined', '[tex]/physics', '[tex]/require', '[tex]/setoptions', '[tex]/tagformat', '[tex]/textcomp', '[tex]/textmacros', '[tex]/unicode', '[tex]/verb', '[tex]/cases', '[tex]/empheq'] 9回目 (3) ['tex', 'mml', 'sre'] 10回目 (4) ['startup', 'input/tex', 'input/tex-full', '[tex]/all-packages'] 11回目 (4) ['[tex]/amsCd', '[tex]/colorV2', '[tex]/configMacros', '[tex]/tagFormat'] 12回目 (1) ['_'] 13回目 (6) ['adaptors', 'components', 'core', 'handlers', 'mathjax', 'util'] 14回目 (1) ['global'] 15回目 (1) ['_'] 16回目 (1) ['input'] 17回目 (1) ['_'] 18回目 (1) ['input'] 19回目 (2) ['mathml_ts', 'mathml'] 20回目 (1) ['_'] 21回目 (1) ['output'] 22回目 (1) ['checkReady'] 23回目 (1) ['_'] 24回目 (1) ['output'] 25回目 (2) ['chtml', 'common'] 26回目 (1) ['fonts'] 27回目 (1) ['fonts'] 28回目 (1) ['fontURL'] 29回目 (1) ['font'] 30回目 (1) ['_'] 31回目 (1) ['ui'] 32回目 (1) ['_'] 33回目 (1) ['a11y']
呼ばれるのは、この9515をコールしたときではなく、後で、違う方法で実行されるように呼ばれるようだ。そのときに、このような引数が渡されて実行される。でも、デバッガによると n には、この関数全体が格納される。おそらく n によってこの関数が実行されるんだろう。論理演算ってそういう解釈があるんだなとは疑問に思いつつも納得しようと思う。調べないとな。33回も呼ばれるんだから、後で、こんなのあったなぁってなるんだろう。先に進もう。
次に実行されるのはObject.defineProperty(e, "__esModule", { value: !0 })
で、Object.defineProperty()はオブジェクトの定義をする命令で、第一引数のオブジェクトに、第二引数のメンバ変数に第三引数を値として設定している。つまり、e.__esModule = {value : !0}
としている。なんで!0なんだろう。!0 って true のことだと思うので、e.__esModule = {value : true}
って感じだと思う。 __esModule は、EcmaScriptに準拠したモジュールかを設定しているとか説明があった。変数 e の扱いを決定するものだな。でも、e.__esModule = true
じゃなくて{value : true}
なんだな。
続けて、xxx = void 0;を設定という形式で
e.MathJax = undefined; e.combineWithMathJax = undefined; e.combineDefaults = undefined; e.combineConfig = undefined; e.isObject = undefined;
としている。e は、どうやら環境変数って意味っぽいな Environments の e だな。MathJax は、このプログラムの核となる設定でcombineは結合とか混合って意味でwithMathJaxはMathJaxと結合するもの。Defaults規定値で結合するもの。Configは設定で結合するもの、isObjectはオブジェクトかどうか。って感じかな。ひとつ感じるのは、まだ何も始まってすらいないという感じだな。これだけおおがかりなことやっていながら、設定するのは、undefined だもんな。
次は var o = r(3282);
が実行されます。rは関数が格納されていて、__webpack_require__です。いやはや、この__webpack_require__(9515)を通じて、__webpack_modules__[9515].call()がされて今にいたっているのに、それが終わるのを待たずして、関数の内で、また新しく__webpack_require__(3282)を実行するようなものですね。確か、この__webpack_require__(9515)の後も同じように__webpack_require__(3282)が実行される流れになっていたような。ここでも実行しようとするんだね。3282は関数の内容が少ない。
o = { VERSION: "3.2.2", __esModule : true } になる。でも、次に呼ばれる__webpack_require__(3282)の結果は e 配列に追加格納されるような。さっき環境変数の e にいくつかundefined値が設定されたものもあったな。そして o にも同じような値を持たせるんだな。今、結構1文字の変数埋まってきてるな。環境変数っぽい e 。今しがた論理演算で込みなのに取得された n 。そして、o 。それから__webpack_require__が格納された r 。9515のcall内での t は r.export という引数が対応する。これは{ export : {} }に対応している。呼ばれる前は t は配列番号の9515を保持するモノとして使われていた。
この後、さらに2つの1文字変数に関数が格納されます。
i 短い関数function i(t) { return "object" == typeof t && null !== t }
、そして s には割かし長めの関数がfunction s(t, e) { … }
。
そして今しがた獲得したiとsの関数をちょっと前に登場した環境変数に格納する。グローバル系の処理が多いね。これって、なんか違うjava Scriptを同時に動かしているsiteなら、変数が重複して動かなくなりそうなもんだけど大丈夫なのかな。
e.isObject = i; e.combineConfig = s;
に格納している。確かにe.isObject(t)は動かすと、t がオブジェクトなのかを識別して、オブジェクトなら1と返却するし、違うなら0になるね。combineConfig は長いよね。簡単にながめてみると。
関数 s は for文で 論理演算の元で格納された関数 n に引数 o を与えながら全ての o の要素分だけ繰り返す。o は Version と __esModuleだけだし、たいした繰り返し処理ではなさそうだ。それよか、この for 文がエグイ記述だな。
var a = n(Object.keys(e)), l = a.next(); !l.done; l = a.next()
ということなんだけど、初期値がカンマ区切りで2個設定されている l = a.next() は次の値なのかな。繰り返し条件の !l.done だから、l.done が 0 の間は、!l.doneが1 なので、繰り返す。l.done が 1 なら終了で、増分は l= a.next で次の配列値が l に入るみたいな感じだな。 ややこしい。e の配列には今は以下の通りになっていて、順番に実行されるのかな。
e.MathJax = undefined; e.combineWithMathJax = undefined; e.combineDefaults = undefined; e.combineConfig = s; e.isObject = i;
こんな感じの環境変数のキーを一個づつ a に取得 l には次の値。繰り返したい要素 2つの値を同時に処理できるというのは斬新だけどやりたい処理ってのは c には 次のキー値 l.value の値が入りつつ、論理演算で、__esModuleという文字列値でないときにtrueである且つ、e[c] instanceof Promise ? null !== e[c] && void 0 !== e[c] && (t[c] = e[c]) : s(t[c], e[c])
?instanceof Promise?ムズッ。Promiseってのは非同期・同期処理についてキャストできたかというのを判定する処理らしい。なんだよ非同期とか同期とか。関数によっては時間がかかるものとかは、順番に処理されることなく、次々と時間がかからない処理を進めていく。非同期。それを順番に処理するのは、同期処理。と言っていると思います。Promiseは処理をするタイミングを調整するものです。そういった関数であるかどうかを判定しているらしい。いづれにしても何がしたいのかわからない。論理演算だけをして、特に代入することもないという。わからん。e[c] instanceof Promiseの結果が true なら null !== e[c] && void 0 !== e[c] && (t[c] = e[c]) で false ならs(t[c], e[c])で、再帰処理がされる。いやそもそも i(t[c]) とか i(e[c]) とか t[c] とか e[c] とか なんだろうね。i(…) は引数がオブジェクトかどうかを判定する関数でした。cは、 MathJax/combineWithMathJax/combineDefaults/combineConfig/isObject/…esModule/で終了条件にesModuleというキーが使われている予感。他のものの場合は、それがオブジェクトなのかを判断するi(e[c])。t[c]。おいておくか。ちょろっとここにブレークポイントを設定してどういうものが実行されるかみてみてみましょう。
実行されるときには t の内容は以下のような値になっているようです。
{version: '3.2.2', _: {}, config: {paths: {mathjax: 'http://localhost:5500/es5'}, source: {}, dependencies: {}, provides: { }, load: Array(0), …}}
eは{loader: {versions: Map(0), ready: ƒ, load: ƒ, preLoad: ƒ, defaultReady: ƒ, …}}で、a = n(Object.key(e)) の a はn('loader')になります。nはちょっと前にあった関数が入っていて、
function(t /* ← 'loader' */) {
var e = "function" == typeof Symbol && Symbol.iterator,
r = e && t[e],/* e : Symbol(Symbol.iterator) && 'loader'[Symbol(Symbol.iterator)] → r : ƒ values() */
n = 0;
if(r) return r.call(t); /* r = function( t /='loader'=/ ){return t /='loader'=/ } → return 'loader' */
if(t && "number" == typeof t.length) return {
next: function() {
return t && n >= t.length && (t = void 0), {
value: t && t[n++],
done: !t
}
}
};
throw new TypeError(e ? "Object is not iterable." : "Symbol.iterator is not defined.")
}
でした。この t が'loader'ってことですね。 l は { value: "loader", done: false, } になります。for文の中身の
var a = n(Object.keys(e)), l = a.next(); !l.done; l = a.next()
この l です。a は {} です。Array Iterator と表現されます。このfor文の使い方は難しい。理解できない。lの中身がそうなる理由が見えてこない。初期値は長い関数によって帰ってくる値で n('loader') の結果が {} で、l = a.next() なんだけど、{ value: "loader", done: false, }っつうね。終了条件の l.done がどこからきたかはわかっていないけど、最初は false なので 1回は処理されるというね。で、おわるとl = a.next() が実行されて次の処理になる。
c = l.Value は最初は loader
t[c] = undefined e[c] = {versions: Map(0), ready: ƒ, load: ƒ, preLoad: ƒ, defaultReady: ƒ, …} e[c] instanceof Promise : false
falseなので、再帰部分が呼ばれる。s(t[c], e[c])。ふむ。いずれにしても、ここでは論理式が書かれているだけで、処理はなにもされなくて、これがエラーにならないかどうかを確かめているだけなのだろう。何もなければ、t そのものが返却される。うまくいかないとエラーになる。
__webpack_modules__[3282].call(r.exports, r, r.exports, __webpack_require__)
3282: function(t, e) {
Object.defineProperty(e, "__esModule", {
value: !0
}), e.VERSION = void 0, e.VERSION = "3.2.2"
},
__webpack_modules__[235].call(r.exports, r, r.exports, __webpack_require__)
235: function(t, e, r) {
var n, o, i = this && this.__values || function(t) {
var e = "function" == typeof Symbol && Symbol.iterator,
r = e && t[e],
n = 0;
if(r) return r.call(t);
if(t && "number" == typeof t.length) return {
next: function() {
return t && n >= t.length && (t = void 0), {
value: t && t[n++],
done: !t
}
}
};
throw new TypeError(e ? "Object is not iterable." : "Symbol.iterator is not defined.")
};
Object.defineProperty(e, "__esModule", {
value: !0
}), e.CONFIG = e.MathJax = e.Loader = e.PathFilters = e.PackageError = e.Package = void 0;
var s = r(9515),
a = r(265),
l = r(265);
Object.defineProperty(e, "Package", {
enumerable: !0,
get: function() {
return l.Package
}
}), Object.defineProperty(e, "PackageError", {
enumerable: !0,
get: function() {
return l.PackageError
}
});
var c, u = r(7525);
if(e.PathFilters = {
source: function(t) {
return e.CONFIG.source.hasOwnProperty(t.name) && (t.name = e.CONFIG.source[t.name]), !0
},
normalize: function(t) {
var e = t.name;
return e.match(/^(?:[a-z]+:\/)?\/|[a-z]:\\|\[/i) || (t.name = "[mathjax]/" + e.replace(/^\.\//, "")), t.addExtension && !e.match(/\.[^\/]+$/) && (t.name += ".js"), !0
},
prefix: function(t) {
for(var r;
(r = t.name.match(/^\[([^\]]*)\]/)) && e.CONFIG.paths.hasOwnProperty(r[1]);) t.name = e.CONFIG.paths[r[1]] + t.name.substr(r[0].length);
return !0
}
}, function(t) {
var r = s.MathJax.version;
t.versions = new Map, t.ready = function() {
for(var t, e, r = [], n = 0; n < arguments.length; n++) r[n] = arguments[n];
0 === r.length && (r = Array.from(a.Package.packages.keys()));
var o = [];
try {
for(var s = i(r), l = s.next(); !l.done; l = s.next()) {
var c = l.value,
u = a.Package.packages.get(c) || new a.Package(c, !0);
o.push(u.promise)
}
} catch(e) {
t = {
error: e
}
} finally {
try {
l && !l.done && (e = s.return) && e.call(s)
} finally {
if(t) throw t.error
}
}
return Promise.all(o)
}, t.load = function() {
for(var r, n, o = [], s = 0; s < arguments.length; s++) o[s] = arguments[s];
if(0 === o.length) return Promise.resolve();
var l = [],
c = function(r) {
var n = a.Package.packages.get(r);
n || (n = new a.Package(r)).provides(e.CONFIG.provides[r]), n.checkNoLoad(), l.push(n.promise.then((function() {
e.CONFIG.versionWarnings && n.isLoaded && !t.versions.has(a.Package.resolvePath(r)) && console.warn("No version information available for component ".concat(r))
})))
};
try {
for(var u = i(o), p = u.next(); !p.done; p = u.next()) {
var h = p.value;
c(h)
}
} catch(t) {
r = {
error: t
}
} finally {
try {
p && !p.done && (n = u.return) && n.call(u)
} finally {
if(r) throw r.error
}
}
return a.Package.loadAll(), Promise.all(l)
}, t.preLoad = function() {
for(var t, r, n = [], o = 0; o < arguments.length; o++) n[o] = arguments[o];
try {
for(var s = i(n), l = s.next(); !l.done; l = s.next()) {
var c = l.value,
u = a.Package.packages.get(c);
u || (u = new a.Package(c, !0)).provides(e.CONFIG.provides[c]), u.loaded()
}
} catch(e) {
t = {
error: e
}
} finally {
try {
l && !l.done && (r = s.return) && r.call(s)
} finally {
if(t) throw t.error
}
}
}, t.defaultReady = function() {
void 0 !== e.MathJax.startup && e.MathJax.config.startup.ready()
}, t.getRoot = function() {
var t = "//../../es5";
if("undefined" != typeof document) {
var e = document.currentScript || document.getElementById("MathJax-script");
e && (t = e.src.replace(/\/[^\/]*$/, ""))
}
return t
}, t.checkVersion = function(n, o, i) {
return t.versions.set(a.Package.resolvePath(n), r), !(!e.CONFIG.versionWarnings || o === r) && (console.warn("Component ".concat(n, " uses ").concat(o, " of MathJax; version in use is ").concat(r)), !0)
}, t.pathFilters = new u.FunctionList, t.pathFilters.add(e.PathFilters.source, 0), t.pathFilters.add(e.PathFilters.normalize, 10), t.pathFilters.add(e.PathFilters.prefix, 20)
}(c = e.Loader || (e.Loader = {})), e.MathJax = s.MathJax, void 0 === e.MathJax.loader) {
(0, s.combineDefaults)(e.MathJax.config, "loader", {
paths: {
mathjax: c.getRoot()
},
source: {},
dependencies: {},
provides: {},
load: [],
ready: c.defaultReady.bind(c),
failed: function(t) {
return console.log("MathJax(".concat(t.package || "?", "): ").concat(t.message))
},
require: null,
pathFilters: [],
versionWarnings: !0
}), (0, s.combineWithMathJax)({
loader: c
});
try {
for(var p = i(e.MathJax.config.loader.pathFilters), h = p.next(); !h.done; h = p.next()) {
var f = h.value;
Array.isArray(f) ? c.pathFilters.add(f[0], f[1]) : c.pathFilters.add(f)
}
} catch(t) {
n = {
error: t
}
} finally {
try {
h && !h.done && (o = p.return) && o.call(p)
} finally {
if(n) throw n.error
}
}
}
e.CONFIG = e.MathJax.config.loader
},
__webpack_modules__[265].call(r.exports, r, r.exports, __webpack_require__)
265: function(t, e, r) {
var n, o = this && this.__extends || (n = function(t, e) {
return n = Object.setPrototypeOf || {
__proto__: []
}
instanceof Array && function(t, e) {
t.__proto__ = e
} || function(t, e) {
for(var r in e) Object.prototype.hasOwnProperty.call(e, r) && (t[r] = e[r])
}, n(t, e)
}, function(t, e) {
if("function" != typeof e && null !== e) throw new TypeError("Class extends value " + String(e) + " is not a constructor or null");
function r() {
this.constructor = t
}
n(t, e), t.prototype = null === e ? Object.create(e) : (r.prototype = e.prototype, new r)
}),
i = this && this.__values || function(t) {
var e = "function" == typeof Symbol && Symbol.iterator,
r = e && t[e],
n = 0;
if(r) return r.call(t);
if(t && "number" == typeof t.length) return {
next: function() {
return t && n >= t.length && (t = void 0), {
value: t && t[n++],
done: !t
}
}
};
throw new TypeError(e ? "Object is not iterable." : "Symbol.iterator is not defined.")
},
s = this && this.__read || function(t, e) {
var r = "function" == typeof Symbol && t[Symbol.iterator];
if(!r) return t;
var n, o, i = r.call(t),
s = [];
try {
for(;
(void 0 === e || e-- > 0) && !(n = i.next()).done;) s.push(n.value)
} catch(t) {
o = {
error: t
}
} finally {
try {
n && !n.done && (r = i.return) && r.call(i)
} finally {
if(o) throw o.error
}
}
return s
},
a = this && this.__spreadArray || function(t, e, r) {
if(r || 2 === arguments.length)
for(var n, o = 0, i = e.length; o < i; o++) !n && o in e || (n || (n = Array.prototype.slice.call(e, 0, o)), n[o] = e[o]);
return t.concat(n || Array.prototype.slice.call(e))
};
Object.defineProperty(e, "__esModule", {
value: !0
}), e.Package = e.PackageError = void 0;
var l = r(235),
c = function(t) {
function e(e, r) {
var n = t.call(this, e) || this;
return n.package = r, n
}
return o(e, t), e
}(Error);
e.PackageError = c;
var u = function() {
function t(e, r) {
void 0 === r && (r = !1), this.isLoaded = !1, this.isLoading = !1, this.hasFailed = !1, this.dependents = [], this.dependencies = [], this.dependencyCount = 0, this.provided = [], this.name = e, this.noLoad = r, t.packages.set(e, this), this.promise = this.makePromise(this.makeDependencies())
}
return Object.defineProperty(t.prototype, "canLoad", {
get: function() {
return 0 === this.dependencyCount && !this.noLoad && !this.isLoading && !this.hasFailed
},
enumerable: !1,
configurable: !0
}), t.resolvePath = function(t, e) {
void 0 === e && (e = !0);
var r = {
name: t,
original: t,
addExtension: e
};
return l.Loader.pathFilters.execute(r), r.name
}, t.loadAll = function() {
var t, e;
try {
for(var r = i(this.packages.values()), n = r.next(); !n.done; n = r.next()) {
var o = n.value;
o.canLoad && o.load()
}
} catch(e) {
t = {
error: e
}
} finally {
try {
n && !n.done && (e = r.return) && e.call(r)
} finally {
if(t) throw t.error
}
}
}, t.prototype.makeDependencies = function() {
var e, r, n = [],
o = t.packages,
c = this.noLoad,
u = this.name,
p = [];
l.CONFIG.dependencies.hasOwnProperty(u) ? p.push.apply(p, a([], s(l.CONFIG.dependencies[u]), !1)) : "core" !== u && p.push("core");
try {
for(var h = i(p), f = h.next(); !f.done; f = h.next()) {
var d = f.value,
m = o.get(d) || new t(d, c);
this.dependencies.indexOf(m) < 0 && (m.addDependent(this, c), this.dependencies.push(m), m.isLoaded || (this.dependencyCount++, n.push(m.promise)))
}
} catch(t) {
e = {
error: t
}
} finally {
try {
f && !f.done && (r = h.return) && r.call(h)
} finally {
if(e) throw e.error
}
}
return n
}, t.prototype.makePromise = function(t) {
var e = this,
r = new Promise((function(t, r) {
e.resolve = t, e.reject = r
})),
n = l.CONFIG[this.name] || {};
return n.ready && (r = r.then((function(t) {
return n.ready(e.name)
}))), t.length && (t.push(r), r = Promise.all(t).then((function(t) {
return t.join(", ")
}))), n.failed && r.catch((function(t) {
return n.failed(new c(t, e.name))
})), r
}, t.prototype.load = function() {
if(!this.isLoaded && !this.isLoading && !this.noLoad) {
this.isLoading = !0;
var e = t.resolvePath(this.name);
l.CONFIG.require ? this.loadCustom(e) : this.loadScript(e)
}
}, t.prototype.loadCustom = function(t) {
var e = this;
try {
var r = l.CONFIG.require(t);
r instanceof Promise ? r.then((function() {
return e.checkLoad()
})).catch((function(r) {
return e.failed("Can't load \"" + t + '"\n' + r.message.trim())
})) : this.checkLoad()
} catch(t) {
this.failed(t.message)
}
}, t.prototype.loadScript = function(t) {
var e = this,
r = document.createElement("script");
r.src = t, r.charset = "UTF-8", r.onload = function(t) {
return e.checkLoad()
}, r.onerror = function(r) {
return e.failed("Can't load \"" + t + '"')
}, document.head.appendChild(r)
}, t.prototype.loaded = function() {
var t, e, r, n;
this.isLoaded = !0, this.isLoading = !1;
try {
for(var o = i(this.dependents), s = o.next(); !s.done; s = o.next()) {
s.value.requirementSatisfied()
}
} catch(e) {
t = {
error: e
}
} finally {
try {
s && !s.done && (e = o.return) && e.call(o)
} finally {
if(t) throw t.error
}
}
try {
for(var a = i(this.provided), l = a.next(); !l.done; l = a.next()) {
l.value.loaded()
}
} catch(t) {
r = {
error: t
}
} finally {
try {
l && !l.done && (n = a.return) && n.call(a)
} finally {
if(r) throw r.error
}
}
this.resolve(this.name)
}, t.prototype.failed = function(t) {
this.hasFailed = !0, this.isLoading = !1, this.reject(new c(t, this.name))
}, t.prototype.checkLoad = function() {
var t = this;
((l.CONFIG[this.name] || {}).checkReady || function() {
return Promise.resolve()
})().then((function() {
return t.loaded()
})).catch((function(e) {
return t.failed(e)
}))
}, t.prototype.requirementSatisfied = function() {
this.dependencyCount && (this.dependencyCount--, this.canLoad && this.load())
}, t.prototype.provides = function(e) {
var r, n;
void 0 === e && (e = []);
try {
for(var o = i(e), s = o.next(); !s.done; s = o.next()) {
var a = s.value,
c = t.packages.get(a);
c || (l.CONFIG.dependencies[a] || (l.CONFIG.dependencies[a] = []), l.CONFIG.dependencies[a].push(a), (c = new t(a, !0)).isLoading = !0), this.provided.push(c)
}
} catch(t) {
r = {
error: t
}
} finally {
try {
s && !s.done && (n = o.return) && n.call(o)
} finally {
if(r) throw r.error
}
}
}, t.prototype.addDependent = function(t, e) {
this.dependents.push(t), e || this.checkNoLoad()
}, t.prototype.checkNoLoad = function() {
var t, e;
if(this.noLoad) {
this.noLoad = !1;
try {
for(var r = i(this.dependencies), n = r.next(); !n.done; n = r.next()) {
n.value.checkNoLoad()
}
} catch(e) {
t = {
error: e
}
} finally {
try {
n && !n.done && (e = r.return) && e.call(r)
} finally {
if(t) throw t.error
}
}
}
}, t.packages = new Map, t
}();
e.Package = u
},
2388: function(t, e, r) {
var n = this && this.__assign || function() {
return n = Object.assign || function(t) {
for(var e, r = 1, n = arguments.length; r < n; r++)
for(var o in e = arguments[r]) Object.prototype.hasOwnProperty.call(e, o) && (t[o] = e[o]);
return t
}, n.apply(this, arguments)
},
o = this && this.__values || function(t) {
var e = "function" == typeof Symbol && Symbol.iterator,
r = e && t[e],
n = 0;
if(r) return r.call(t);
if(t && "number" == typeof t.length) return {
next: function() {
return t && n >= t.length && (t = void 0), {
value: t && t[n++],
done: !t
}
}
};
throw new TypeError(e ? "Object is not iterable." : "Symbol.iterator is not defined.")
},
i = this && this.__read || function(t, e) {
var r = "function" == typeof Symbol && t[Symbol.iterator];
if(!r) return t;
var n, o, i = r.call(t),
s = [];
try {
for(;
(void 0 === e || e-- > 0) && !(n = i.next()).done;) s.push(n.value)
} catch(t) {
o = {
error: t
}
} finally {
try {
n && !n.done && (r = i.return) && r.call(i)
} finally {
if(o) throw o.error
}
}
return s
},
s = this && this.__spreadArray || function(t, e, r) {
if(r || 2 === arguments.length)
for(var n, o = 0, i = e.length; o < i; o++) !n && o in e || (n || (n = Array.prototype.slice.call(e, 0, o)), n[o] = e[o]);
return t.concat(n || Array.prototype.slice.call(e))
};
Object.defineProperty(e, "__esModule", {
value: !0
}), e.CONFIG = e.MathJax = e.Startup = void 0;
var a, l = r(9515),
c = r(8666),
u = r(7233);
! function(t) {
var a, l, u = new c.PrioritizedList;
function h(e) {
return a.visitTree(e, t.document)
}
function f() {
a = new e.MathJax._.core.MmlTree.SerializedMmlVisitor.SerializedMmlVisitor, l = e.MathJax._.mathjax.mathjax, t.input = v(), t.output = _(), t.adaptor = S(), t.handler && l.handlers.unregister(t.handler), t.handler = M(), t.handler && (l.handlers.register(t.handler), t.document = O())
}
function d() {
var e, r;
t.input && t.output && m();
var n = t.output ? t.output.name.toLowerCase() : "";
try {
for(var i = o(t.input), s = i.next(); !s.done; s = i.next()) {
var a = s.value,
l = a.name.toLowerCase();
g(l, a), b(l, a), t.output && y(l, n, a)
}
} catch(t) {
e = {
error: t
}
} finally {
try {
s && !s.done && (r = i.return) && r.call(i)
} finally {
if(e) throw e.error
}
}
}
function m() {
e.MathJax.typeset = function(e) {
void 0 === e && (e = null), t.document.options.elements = e, t.document.reset(), t.document.render()
}, e.MathJax.typesetPromise = function(e) {
return void 0 === e && (e = null), t.document.options.elements = e, t.document.reset(), l.handleRetriesFor((function() {
t.document.render()
}))
}, e.MathJax.typesetClear = function(e) {
void 0 === e && (e = null), e ? t.document.clearMathItemsWithin(e) : t.document.clear()
}
}
function y(r, n, o) {
var i = r + "2" + n;
e.MathJax[i] = function(e, r) {
return void 0 === r && (r = {}), r.format = o.name, t.document.convert(e, r)
}, e.MathJax[i + "Promise"] = function(e, r) {
return void 0 === r && (r = {}), r.format = o.name, l.handleRetriesFor((function() {
return t.document.convert(e, r)
}))
}, e.MathJax[n + "Stylesheet"] = function() {
return t.output.styleSheet(t.document)
}, "getMetricsFor" in t.output && (e.MathJax.getMetricsFor = function(e, r) {
return t.output.getMetricsFor(e, r)
})
}
function g(r, n) {
var o = e.MathJax._.core.MathItem.STATE;
e.MathJax[r + "2mml"] = function(e, r) {
return void 0 === r && (r = {}), r.end = o.CONVERT, r.format = n.name, h(t.document.convert(e, r))
}, e.MathJax[r + "2mmlPromise"] = function(e, r) {
return void 0 === r && (r = {}), r.end = o.CONVERT, r.format = n.name, l.handleRetriesFor((function() {
return h(t.document.convert(e, r))
}))
}
}
function b(t, r) {
e.MathJax[t + "Reset"] = function() {
for(var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e];
return r.reset.apply(r, s([], i(t), !1))
}
}
function v() {
var r, n, i = [];
try {
for(var s = o(e.CONFIG.input), a = s.next(); !a.done; a = s.next()) {
var l = a.value,
c = t.constructors[l];
if(!c) throw Error('Input Jax "' + l + '" is not defined (has it been loaded?)');
i.push(new c(e.MathJax.config[l]))
}
} catch(t) {
r = {
error: t
}
} finally {
try {
a && !a.done && (n = s.return) && n.call(s)
} finally {
if(r) throw r.error
}
}
return i
}
function _() {
var r = e.CONFIG.output;
if(!r) return null;
var n = t.constructors[r];
if(!n) throw Error('Output Jax "' + r + '" is not defined (has it been loaded?)');
return new n(e.MathJax.config[r])
}
function S() {
var r = e.CONFIG.adaptor;
if(!r || "none" === r) return null;
var n = t.constructors[r];
if(!n) throw Error('DOMAdaptor "' + r + '" is not defined (has it been loaded?)');
return n(e.MathJax.config[r])
}
function M() {
var r, n, i = e.CONFIG.handler;
if(!i || "none" === i || !t.adaptor) return null;
var s = t.constructors[i];
if(!s) throw Error('Handler "' + i + '" is not defined (has it been loaded?)');
var a = new s(t.adaptor, 5);
try {
for(var l = o(u), c = l.next(); !c.done; c = l.next()) {
a = c.value.item(a)
}
} catch(t) {
r = {
error: t
}
} finally {
try {
c && !c.done && (n = l.return) && n.call(l)
} finally {
if(r) throw r.error
}
}
return a
}
function O(r) {
return void 0 === r && (r = null), l.document(r || e.CONFIG.document, n(n({}, e.MathJax.config.options), {
InputJax: t.input,
OutputJax: t.output
}))
}
t.constructors = {}, t.input = [], t.output = null, t.handler = null, t.adaptor = null, t.elements = null, t.document = null, t.promise = new Promise((function(e, r) {
t.promiseResolve = e, t.promiseReject = r
})), t.pagePromise = new Promise((function(t, e) {
var n = r.g.document;
if(n && n.readyState && "complete" !== n.readyState && "interactive" !== n.readyState) {
var o = function() {
return t()
};
n.defaultView.addEventListener("load", o, !0), n.defaultView.addEventListener("DOMContentLoaded", o, !0)
} else t()
})), t.toMML = h, t.registerConstructor = function(e, r) {
t.constructors[e] = r
}, t.useHandler = function(t, r) {
void 0 === r && (r = !1), e.CONFIG.handler && !r || (e.CONFIG.handler = t)
}, t.useAdaptor = function(t, r) {
void 0 === r && (r = !1), e.CONFIG.adaptor && !r || (e.CONFIG.adaptor = t)
}, t.useInput = function(t, r) {
void 0 === r && (r = !1), p && !r || e.CONFIG.input.push(t)
}, t.useOutput = function(t, r) {
void 0 === r && (r = !1), e.CONFIG.output && !r || (e.CONFIG.output = t)
}, t.extendHandler = function(t, e) {
void 0 === e && (e = 10), u.add(t, e)
}, t.defaultReady = function() {
f(), d(), t.pagePromise.then((function() {
return e.CONFIG.pageReady()
})).then((function() {
return t.promiseResolve()
})).catch((function(e) {
return t.promiseReject(e)
}))
}, t.defaultPageReady = function() {
return e.CONFIG.typeset && e.MathJax.typesetPromise ? e.MathJax.typesetPromise(e.CONFIG.elements) : Promise.resolve()
}, t.getComponents = f, t.makeMethods = d, t.makeTypesetMethods = m, t.makeOutputMethods = y, t.makeMmlMethods = g, t.makeResetMethod = b, t.getInputJax = v, t.getOutputJax = _, t.getAdaptor = S, t.getHandler = M, t.getDocument = O
}(a = e.Startup || (e.Startup = {})), e.MathJax = l.MathJax, void 0 === e.MathJax._.startup && ((0, l.combineDefaults)(e.MathJax.config, "startup", {
input: [],
output: "",
handler: null,
adaptor: null,
document: "undefined" == typeof document ? "" : document,
elements: null,
typeset: !0,
ready: a.defaultReady.bind(a),
pageReady: a.defaultPageReady.bind(a)
}), (0, l.combineWithMathJax)({
startup: a,
options: {}
}), e.MathJax.config.startup.invalidOption && (u.OPTIONS.invalidOption = e.MathJax.config.startup.invalidOption), e.MathJax.config.startup.optionError && (u.OPTIONS.optionError = e.MathJax.config.startup.optionError)), e.CONFIG = e.MathJax.config.startup;
var p = 0 !== e.CONFIG.input.length
},
関連情報