「MathJaxをデバッグしてJavaScriptの理解を深める ページ4」の版間の差分

提供:yonewiki
 
(同じ利用者による、間の8版が非表示)
606行目: 606行目:
},
},
</syntaxhighlight>
</syntaxhighlight>
 呼ばれるときの引数は{"0": {}, "1": undefined,} こんな感じ。Object.assign は空の関数で n はfunction(t) の内容になります。でもこの関数も呼ばれることはないようです。


 
 


===== o &#x3D; =====
===== o &#x3D; =====
<syntaxhighlight lang="javascript">
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.")
}
</syntaxhighlight>
 t は['tex', 'mml'] のような配列です。これを r = ['tex', 'mml'] [Symbol.iteretor] のようにするとユーザ定義の反復可能項目という変数が作られ。console.log([...r]) とすると、すべての項目が順次呼び出される仕組みが構築されているため展開されます。[...r] は for … in … や for … of … という構文でも反復可能項目は展開されます。つまり前半は、受け取った配列引数を反復可能項目を作るための処理となります。t が文字列や配列の時は if(r) は成立して、 return ['tex', 'mml'] [Symbol.iteretor].call(['tex', 'mml'])のようなものを返却します。この値はネットには解説がないのですが、結果としては反復可能項目が返っているようです。 反復可能項目の .call というのがよくわからない。この call では this に該当するものが配列そのものであるとしています。反復可能項目でありながら、配列そのものも保持しているという、特殊な反復可能項目を作っているのかな。わからん。知らんけど。ってやつだな。今年は知らんけど流行ったらしい。大阪では昔からありますけどね。t が数値の時は r = 数値[Symbol.iteretor]となって、r は未定義となります。しかし数値.lengthも未定義で数値型にはならない。どういうときに次の if が成立するんだろうな。ブレークポイント設定したけど、if(r)が成立しないパターンなかったな。全部の同じような仕組みのところが44か所もありますが、全てにブレークポイントを設定しても成立しないパターンはゼロ。だいぶコード削っても動くには動くらしい。エラー処理が多すぎて無駄が多いような気もする。まったく同じようなコードばっかり44か所。これだけ関数化しておきながらややこしいところは繰り返しまくり、簡単なとこは複雑関数化みたいなことをやってる気がする。まぁな、成立しないパターンがあったら例外がスローされるからね。そりゃそうだ。って感じもする。


 
 
638行目: 658行目:


===== function f() =====
===== function f() =====
 以下のような関数です。
<syntaxhighlight lang="javascript">
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()
  )
}
</syntaxhighlight>
 a は以下のような値が格納されるmapオブジェクトが関数を保持するような構造。
<syntaxhighlight lang="javascript">
{
size: 5,
Map(5)
{"inferredMrow" => function(t, e) {
  var r, n, o = [];
  try {
    for(var s = i(t.childNodes), a = s.next(); !a.done; a = s.next()) {
      var l = a.value;
      o.push(this.visitNode(l, e))
    }
  }
  catch(t) { r = { error: t } }
  finally {
    try { a && !a.done && (n = s.return) && n.call(s) }
    finally { if(r) throw r.error }
  }
  return o.join("\\n")
}},
{"annotation" => function(t, e) { /* annotation は注釈という意味 */
  return e + "<annotation" + this.getAttributes(t) + ">" + this.childNodeMml(t, "", "") + "</annotation>"
}},
{"TeXAtom" => function(t, e) { /* TeXAtom ってAtomエディタで使えるってことかな。 */
  var r = this.childNodeMml(t, e + "  ", "\\n");
  return e + "<mrow" + this.getAttributes(t) + ">" + (r.match(/\\S/) ? "\\n" + r + e : "") + "</mrow>"
}},
{"text" => function(t, e) {
  return this.quoteHTML(t.getText())
}},
{"XML" => function(t, e) {
  return e + t.getSerializedXML()
}}
}
</syntaxhighlight>
*inferredMrow
: t.childNodes は、[mi(a),mo(≠),mn(0)] のような配列で最初に呼ばれます。これはサンプルHTMLのインラインの数式$ a \ne 0 $ というのが対応していると思います。この配列がひとつづつ処理されて、l = mi(a) で e = '&nbsp;&nbsp;' は this.visitNode(l, e) = '&nbsp;&nbsp;<mi>a</mi>'という値でこれを o にスタックします。これはかなり具体的に mml(Math Markup Language) を構成している処理ですね。こういうのを解き明かしたかったというところが初めて登場しました。
<syntaxhighlight lang="javascript">
t.prototype.visitNode = function(t) { /* t = mi(a) */
  for(var e = [], r = 1; r < arguments.length; r++)
    e[r - 1] = arguments[r];/* arguments[0] = 'mi(a)', arguments[1] = '  ' */
  var n = this.nodeHandlers.get(t.kind) ||  /* t.kind = mi */
  this.visitDefault;
  return
  n.call.apply(
    n,
    i(
      [this, t],
      o(e),
      !1 /* false */
    )
  )
}
</syntaxhighlight>
 this.visitDefault は以下のような関数です。
<syntaxhighlight lang="javascript">
function(t, e) {/* t = mi(a), e = '  ' のとき */
  var r = t.kind,
  n = s(t.isToken || 0 === t.childNodes.length ? ["", ""] : ["\n", e], 2),
    /* t.isToken = true, t.childNodes.length = 1 */
    /* n = ["\n", "  "] */
  o = n[0], /* "\n" */
  i = n[1], /* "  " */
  a = this.childNodeMml(t, e + "  ", o); /* ( mi(a), "    ", \n) */
  return e + "<" + r + this.getAttributes(t) + ">" + (a.match(/\S/) ? o + a + i : "") + "</" + r + ">"
  /* "  <mi>\na\n</mi>" */
}
</syntaxhighlight>
 正規表現検索の \S はスペース以外の一文字に一致したらという意味で、一致するので、二項演算子の成立時の o + a + i が適用されます。
 childNodeMml は以下のような関数です。childNodes には mi(a) の a が保持されています。
<syntaxhighlight lang="javascript">
r.prototype.childNodeMml = function(t, e, r) { /* mi(a) , '    ', \n */
  var n, o, s = "";
  try {
    for(var a = i(t.childNodes), l = a.next(); !l.done; l = a.next()) {
      var c = l.value;
      s += this.visitNode(c, e) + r /*c = 'a', e = '    ' → 'a' + \n */
    }
  }
  catch(t) { n = { error: t } }
  finally {
    try { l && !l.done && (o = a.return) && o.call(a) }
    finally { if(n) throw n.error }
  }
  return s
}
</syntaxhighlight>
<syntaxhighlight lang="javascript">
.visitNode(t, e) {return this.quoteHTML(t.getText()) } /* return 'a' */
</syntaxhighlight>
 今回はAttributes値は処理されませんが、以下のような関数で文字列を返します。
<syntaxhighlight lang="javascript">
function(e) {
  return t.prototype.getAttributes.call(this, e).replace(/ ?id=".*?"/, "")
}
</syntaxhighlight>
 getAttributesは以下のような関数です。今回は使われません。
<syntaxhighlight lang="javascript">
r.prototype.getAttributes = function(t) {
  var e, r, n = [],
    o = this.constructor.defaultAttributes[t.kind] || {},
    s = Object.assign({}, o, this.getDataAttributes(t), t.attributes.getAllAttributes()),
    a = this.constructor.variants;
  s.hasOwnProperty("mathvariant") && a.hasOwnProperty(s.mathvariant) && (s.mathvariant = a[s.mathvariant]);
  try {
    for(var l = i(Object.keys(s)), c = l.next(); !c.done; c = l.next()) {
      var u = c.value,
        p = String(s[u]);
      void 0 !== p && n.push(u + '="' + this.quoteHTML(p) + '"')
    }
  } catch(t) {
    e = {
      error: t
    }
  } finally {
    try {
      c && !c.done && (r = l.return) && r.call(l)
    } finally {
      if(e) throw e.error
    }
  }
  return n.length ? " " + n.join(" ") : ""
}
</syntaxhighlight>
 結果として "  <mi>\na\n</mi>" が返り値になります。 続く配列値の処理も同様に行われ、≠ &<span>#</span>x2260; が含まれる。 "  <mo>\n≠\n</mo> 最後に <mn>\n0\n</mn> という感じです。


 
 

2022年12月9日 (金) 16:46時点における最新版

VScodeで簡易WebServerの元でデバッグに戻る。

概要

 MathJaxをデバッグしてJavaScriptの理解を深める ページ3の続きです。

[1] [2] [3] [4]

 

__webpack_modules__[2388].call(r.exports, r, r.exports, __webpack_require__)

 もう以前のコードで呼ばれている関数ばかりですが、復習かねて、順番に見ていきます。みていったところで、ぼんやりとしか理解できないコードですけど。

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; 
  var l = r(9515);
  var  c = r(8666);
  var  u = r(7233);
  ! function(t) {
    var a;
    var l;
    var 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
},

 

Object.defineProperty

 n,o,i,s の関数定義が行われたのち実行されます。以下のような関数です。


Object.defineProperty(e, "__esModule", {value: !0});


 で、e.__esModule = true; のような操作が行われます。正しくはObject.definePropertyのような処理です。

 

e.CONFIG = e.MathJax = e.Startup = void 0;

 e に 3つのメンバ変数。正しくはプロパティですね。 CONFIG MathJax Startup を作り、undefined = void 0 を格納します。

 

l = r(9515)

 既に定義されている関数なのでここでは、実際には定義されません。こんなのばっかりだな MathJax 無駄が多い。もう定義されている場合があるのに、っていうね。直線的に追ってるので、それ以外のパターンなんかあるのかって思っちゃう。

 

c = r(8666)

 これも、既に定義されている関数なのでここでは、実際には定義されません。

 

u = r(7233)

 これは今から初めて呼び出される。関数を定義しているだけではないので、一部は実際に処理もされます。以下のようなコードです。


7233: function(t, e) {
  var r = 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.")
    },
    n = 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
    },

    o = 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.lookup = 
  e.separateOptions = 
  e.selectOptionsFromKeys = 
  e.selectOptions = 
  e.userOptions = 
  e.defaultOptions = 
  e.insert = 
  e.copy = 
  e.keys = 
  e.makeArray = 
  e.expandable = 
  e.Expandable = 
  e.OPTIONS = 
  e.REMOVE = 
  e.APPEND = 
  e.isObject = void 0;

  var i = {}.constructor;

  function s(t) {
    return "object" == typeof t && null !== t && (t.constructor === i || t.constructor === a)
  }
  e.isObject = s, 
  e.APPEND = "[+]", 
  e.REMOVE = "[-]", 
  e.OPTIONS = {
    invalidOption: "warn",
    optionError: function(t, r) {
      if("fatal" === e.OPTIONS.invalidOption) throw new Error(t);
      console.warn("MathJax: " + t)
    }
  };
  var a = function() {};

  function l(t) {
    return Object.assign(Object.create(a.prototype), t)
  }

  function c(t) {
    return t ? Object.keys(t).concat(Object.getOwnPropertySymbols(t)) : []
  }

  function u(t) {
    var e, n, o = {};
    try {
      for(var i = r(c(t)), h = i.next(); !h.done; h = i.next()) {
        var f = h.value,
          d = Object.getOwnPropertyDescriptor(t, f),
          m = d.value;
        Array.isArray(m) ? 
          d.value = p([], m, !1) 
        : 
          s(m) && 
          (d.value = u(m)), 
          d.enumerable && 
          (o[f] = d)
      }
    } 
    catch(t) { e = { error: t } } 
    finally {
      try { h && !h.done && (n = i.return) && n.call(i) } 
      finally { if(e) throw e.error }
    }
    return Object.defineProperties(t.constructor === a ? l({}) : {}, o)
  }

  function p(t, i, l) {
    var h, f;
    void 0 === l && (l = !0);
    var d = function(r) {
      if(l && void 0 === t[r] && t.constructor !== a) 
        return "symbol" == typeof r && 
        (r = r.toString()), 
        e.OPTIONS.optionError('Invalid option "'.concat(r, '" (no default value).'), r), 
        "continue";
      var h = i[r],
        f = t[r];
      if(!s(h) || null === f || "object" != typeof f && "function" != typeof f) 
        Array.isArray(h) ? 
          (t[r] = [], p(t[r], h, !1)) 
        : 
          s(h) ? t[r] = u(h) : t[r] = h;
      else {
        var d = c(h);
        Array.isArray(f) && 
        (
          1 === d.length && (d[0] === e.APPEND || d[0] === e.REMOVE) && 
          Array.isArray(h[d[0]]) || 
          2 === d.length && 
          d.sort().join(",") === e.APPEND + "," + e.REMOVE && 
          Array.isArray(h[e.APPEND]) && 
          Array.isArray(h[e.REMOVE])
        ) ? 
          (h[e.REMOVE] && 
          (f = t[r] = f.filter((function(t) {
            return h[e.REMOVE].indexOf(t) < 0
          }))), 
          h[e.APPEND] && 
          (t[r] = o(o([], n(f), !1), n(h[e.APPEND]), !1))) 
        : 
          p(f, h, l)
      }
    };
    try {
      for(var m = r(c(i)), y = m.next(); !y.done; y = m.next()) {
        d(y.value)
      }
    } 
    catch(t) { h = { error: t } } 
    finally {
      try { y && !y.done && (f = m.return) && f.call(m) } 
      finally { if(h) throw h.error }
    }
    return t
  }

  function h(t) {
    for(var e, n, o = [], i = 1; i < arguments.length; i++) o[i - 1] = arguments[i];
    var s = {};
    try {
      for(var a = r(o), l = a.next(); !l.done; l = a.next()) {
        var c = l.value;
        t.hasOwnProperty(c) && (s[c] = t[c])
      }
    } 
    catch(t) { e = { error: t } } 
    finally {
      try { l && !l.done && (n = a.return) && n.call(a) } 
      finally { if(e) throw e.error }
    }
    return s
  }
  e.Expandable = a, 
  e.expandable = l, 
  e.makeArray = function(t) {
    return Array.isArray(t) ? t : [t]
  }, 
  e.keys = c, 
  e.copy = u, 
  e.insert = p, 
  e.defaultOptions = function(t) {
    for(var e = [], r = 1; r < arguments.length; r++) 
      e[r - 1] = arguments[r];
    return e.forEach((function(e) {
      return p(t, e, !1)
    })), 
    t
  }, 
  e.userOptions = function(t) {
    for(var e = [], r = 1; r < arguments.length; r++) 
      e[r - 1] = arguments[r];
    return e.forEach((function(e) {
      return p(t, e, !0)
    })),
    t
  }, 
  e.selectOptions = h, e.selectOptionsFromKeys = function(t, e) {
    return h.apply(void 0, o([t], n(Object.keys(e)), !1))
  }, 
  e.separateOptions = function(t) {
    for(var e, n, o, i, s = [], a = 1; a < arguments.length; a++) 
      s[a - 1] = arguments[a];
    var l = [];
    try {
      for(var c = r(s), u = c.next(); !u.done; u = c.next()) {
        var p = u.value,
          h = {},
          f = {};
        try {
          for(var d = (o = void 0, r(Object.keys(t || {}))), m = d.next(); !m.done; m = d.next()) {
            var y = m.value;
            (void 0 === p[y] ? f : h)[y] = t[y]
          }
        } 
        catch(t) { o = { error: t } } 
        finally {
          try { m && !m.done && (i = d.return) && i.call(d) } 
          finally { if(o) throw o.error }
        }
        l.push(h), t = f
      }
    } 
    catch(t) { e = { error: t } } 
    finally {
      try { u && !u.done && (n = c.return) && n.call(c) } 
      finally { if(e) throw e.error }
    }
    return l.unshift(t), l
  }, 
  e.lookup = function(t, e, r) {
    return void 0 === r && (r = null), e.hasOwnProperty(t) ? e[t] : r
  }
}

 

n =

 変数 n に定義されるコードはこんなの。

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)
},

 呼ばれるときの引数は{"0": {}, "1": undefined,} こんな感じ。Object.assign は空の関数で n はfunction(t) の内容になります。でもこの関数も呼ばれることはないようです。

 

o =
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.")
}

 t は['tex', 'mml'] のような配列です。これを r = ['tex', 'mml'] [Symbol.iteretor] のようにするとユーザ定義の反復可能項目という変数が作られ。console.log([...r]) とすると、すべての項目が順次呼び出される仕組みが構築されているため展開されます。[...r] は for … in … や for … of … という構文でも反復可能項目は展開されます。つまり前半は、受け取った配列引数を反復可能項目を作るための処理となります。t が文字列や配列の時は if(r) は成立して、 return ['tex', 'mml'] [Symbol.iteretor].call(['tex', 'mml'])のようなものを返却します。この値はネットには解説がないのですが、結果としては反復可能項目が返っているようです。 反復可能項目の .call というのがよくわからない。この call では this に該当するものが配列そのものであるとしています。反復可能項目でありながら、配列そのものも保持しているという、特殊な反復可能項目を作っているのかな。わからん。知らんけど。ってやつだな。今年は知らんけど流行ったらしい。大阪では昔からありますけどね。t が数値の時は r = 数値[Symbol.iteretor]となって、r は未定義となります。しかし数値.lengthも未定義で数値型にはならない。どういうときに次の if が成立するんだろうな。ブレークポイント設定したけど、if(r)が成立しないパターンなかったな。全部の同じような仕組みのところが44か所もありますが、全てにブレークポイントを設定しても成立しないパターンはゼロ。だいぶコード削っても動くには動くらしい。エラー処理が多すぎて無駄が多いような気もする。まったく同じようなコードばっかり44か所。これだけ関数化しておきながらややこしいところは繰り返しまくり、簡単なとこは複雑関数化みたいなことをやってる気がする。まぁな、成立しないパターンがあったら例外がスローされるからね。そりゃそうだ。って感じもする。


 

i =

 

s =

 

! function(t)

 c.PrioritizedList は以下のような関数です。オブジェクトの itemsプロパティの配列を空にするという初期化処理です。Promiseで管理する処理順のPriorityのListを構築するもののようです。


 
function t() {
  this.items = [], this.items = []
}

 

function h(e)

 

function f()

 以下のような関数です。

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()
  )
}

 a は以下のような値が格納されるmapオブジェクトが関数を保持するような構造。

{
size: 5, 
Map(5)
{"inferredMrow" => function(t, e) {
  var r, n, o = [];
  try {
    for(var s = i(t.childNodes), a = s.next(); !a.done; a = s.next()) {
      var l = a.value;
      o.push(this.visitNode(l, e))
    }
  } 
  catch(t) { r = { error: t } } 
  finally {
    try { a && !a.done && (n = s.return) && n.call(s) } 
    finally { if(r) throw r.error }
  }
  return o.join("\\n")
}}, 
{"annotation" => function(t, e) { /* annotation は注釈という意味 */
  return e + "<annotation" + this.getAttributes(t) + ">" + this.childNodeMml(t, "", "") + "</annotation>"
}}, 
{"TeXAtom" => function(t, e) { /* TeXAtom ってAtomエディタで使えるってことかな。 */
  var r = this.childNodeMml(t, e + "  ", "\\n");
  return e + "<mrow" + this.getAttributes(t) + ">" + (r.match(/\\S/) ? "\\n" + r + e : "") + "</mrow>"
}}, 
{"text" => function(t, e) {
  return this.quoteHTML(t.getText())
}}, 
{"XML" => function(t, e) {
  return e + t.getSerializedXML()
}}
}
  • inferredMrow
 t.childNodes は、[mi(a),mo(≠),mn(0)] のような配列で最初に呼ばれます。これはサンプルHTMLのインラインの数式$ a \ne 0 $ というのが対応していると思います。この配列がひとつづつ処理されて、l = mi(a) で e = '  ' は this.visitNode(l, e) = '  <mi>a</mi>'という値でこれを o にスタックします。これはかなり具体的に mml(Math Markup Language) を構成している処理ですね。こういうのを解き明かしたかったというところが初めて登場しました。


t.prototype.visitNode = function(t) { /* t = mi(a) */
  for(var e = [], r = 1; r < arguments.length; r++) 
    e[r - 1] = arguments[r];/* arguments[0] = 'mi(a)', arguments[1] = '  ' */
  var n = this.nodeHandlers.get(t.kind) ||  /* t.kind = mi */
  this.visitDefault;
  return 
  n.call.apply(
    n, 
    i(
      [this, t], 
      o(e), 
      !1 /* false */
    )
  )
}


 this.visitDefault は以下のような関数です。


function(t, e) {/* t = mi(a), e = '  ' のとき */
  var r = t.kind,
  	n = s(t.isToken || 0 === t.childNodes.length ? ["", ""] : ["\n", e], 2),
    /* t.isToken = true, t.childNodes.length = 1 */
    /* n = ["\n", "  "] */
  	o = n[0], /* "\n" */
  	i = n[1], /* "  " */
  	a = this.childNodeMml(t, e + "  ", o); /* ( mi(a), "    ", \n) */
  return e + "<" + r + this.getAttributes(t) + ">" + (a.match(/\S/) ? o + a + i : "") + "</" + r + ">"
  /* "  <mi>\na\n</mi>" */ 
}

 正規表現検索の \S はスペース以外の一文字に一致したらという意味で、一致するので、二項演算子の成立時の o + a + i が適用されます。


 childNodeMml は以下のような関数です。childNodes には mi(a) の a が保持されています。


r.prototype.childNodeMml = function(t, e, r) { /* mi(a) , '    ', \n */
  var n, o, s = "";
  try {
    for(var a = i(t.childNodes), l = a.next(); !l.done; l = a.next()) {
      var c = l.value;
      s += this.visitNode(c, e) + r /*c = 'a', e = '    ' → 'a' + \n */
    }
  } 
  catch(t) { n = { error: t } } 
  finally {
    try { l && !l.done && (o = a.return) && o.call(a) } 
    finally { if(n) throw n.error }
  }
  return s
}


.visitNode(t, e) {return this.quoteHTML(t.getText()) } /* return 'a' */

 今回はAttributes値は処理されませんが、以下のような関数で文字列を返します。

function(e) {
  return t.prototype.getAttributes.call(this, e).replace(/ ?id=".*?"/, "")
}


 getAttributesは以下のような関数です。今回は使われません。


r.prototype.getAttributes = function(t) {
  var e, r, n = [],
    o = this.constructor.defaultAttributes[t.kind] || {},
    s = Object.assign({}, o, this.getDataAttributes(t), t.attributes.getAllAttributes()),
    a = this.constructor.variants;
  s.hasOwnProperty("mathvariant") && a.hasOwnProperty(s.mathvariant) && (s.mathvariant = a[s.mathvariant]);
  try {
    for(var l = i(Object.keys(s)), c = l.next(); !c.done; c = l.next()) {
      var u = c.value,
        p = String(s[u]);
      void 0 !== p && n.push(u + '="' + this.quoteHTML(p) + '"')
    }
  } catch(t) {
    e = {
      error: t
    }
  } finally {
    try {
      c && !c.done && (r = l.return) && r.call(l)
    } finally {
      if(e) throw e.error
    }
  }
  return n.length ? " " + n.join(" ") : ""
}

 結果として " <mi>\na\n</mi>" が返り値になります。 続く配列値の処理も同様に行われ、≠ &#x2260; が含まれる。 " <mo>\n≠\n</mo> 最後に <mn>\n0\n</mn> という感じです。

 

function d()

 

function m()

 

function y(r, n, o)

 

function g(r, n)

 

function b(t, r)

 

function v()

 

function _()

 

function S()

 

function M()

 

function O(r)

 

t

 

e

 

l.combineDefaults

 

l.combineWithMathJax

 

e.MathJax.config,e.CONFIG

 

ページ

 

関連情報

 MathJax

 

VScodeで簡易WebServerの元でデバッグに戻る。