Upgrade to Pro — share decks privately, control downloads, hide ads and more …

あなたの知らない Function.prototype.toString() の世界

mizdra
November 22, 2024

あなたの知らない Function.prototype.toString() の世界

JSConf JP 2024 の発表資料です。

---

JavaScript には Function.prototype.toString() という API があります。この API を使うと、関数本体のソースコードを文字列として取得できます。 一見すると何の使い道があるか分からないかもしれません。しかし、関数本体のソースコードを取得できるということは、実行時に関数のソースコードを静的解析できることを意味します。また、関数をシリアライズしてどこかに転送した後、デシリアライズして実行するといったことも可能です。この特徴は、JavaScript に大きな力をもたらします。 このトークでは、 Function.prototype.toString() はどんな API なのか、どういう使い道があるのか、世の中のライブラリで利用されている実用的なものから、狂った使い方まで紹介します。

- リモート関数 (puppeteer の page.evaluate())
- ネイティブコード判定
- tempalte literal を使わない複数行文字列リテラル
- etc...

mizdra

November 22, 2024
Tweet

More Decks by mizdra

Other Decks in Technology

Transcript

  1. 6 Function.prototype. toString() どんな API? • 関数のソースコードを取り出せる API • 関数

    (例: add) に対して add.toString() を呼び出す ◦ add 関数のソースコードが得られる
  2. 18 ブラウザ上で関数を実行する仕組み • さっきと同じ ◦ 1. Node.js 側: fn.toString() ◦

    2. Node.js 側: それをブラウザに送信 ◦ 3. ブラウザ側: const fn = eval(fnStr) ◦ 4. ブラウザ側: fn() で実行 • ブラウザ上で fn() が実行される!
  3. 20 Function.prototype. toString() ソースコードが取り出せると言うけど • 実は必ずしもそうではない • 例: alert ◦

    自分が書いた関数ではなく、組み込みの関数 ◦ toString() するとどうなる?
  4. 24 Function.prototype. toString() 余談: core-js • core-js の polyfill は

    JavaScript で書かれてるけど... ◦ ネイティブコードであるかのように偽装してる
  5. 27 AngularJS の Dependency Injection • AngularJS: Viewフレームワーク ◦ 2009

    年リリース、現在 EoL ◦ 注意: 後継とされる Angular とはだいぶ別物 ▪ 混同しないように! • 引数を使い、Controller に Service を DI できる ◦ Function.prototype.toString() が使われてる
  6. 32 Dependency Injection ② 引数リストから $scope, greeter の 2 つの

    Service に依存してることを推測 ③ランタイムが $scope, greeter を DI する
  7. 35 minify すると壊れる • どういうことか ◦ minify 前: ($scope, greeter)

    => {...} ◦ minify 後: (a, b) => {...} • Service 名が推測できなくなる ◦ DI 失敗
  8. 36 回避策 1. 文字列で Service 名を埋め込む ◦ `ctrl.$inject = ['$scope',

    'greeter']` ◦ 自分で書いてるコードなら文字列形式に書き換えできるが... ▪ 3rd-party ライブラリ中のコードの書き換えは厳しい 2. 識別子だけ minify やめる ◦ `minifyOption: { minifyIdentifiers: false }` ◦ 弊社ではやってた
  9. 37 何故こうなってるのか • 今だったら ◦ bundle して、minify するのが当たり前 ◦ minify

    すると壊れる、は考えられない • 当時は bundler なかった ◦ minify も今ほど気軽にできない • 当時の時代背景故、こうなってる
  10. 42 まとめ • Function.prototype.toString() でできること ◦ 関数の転送 ◦ ネイティブコード判定 ◦

    Dependency Injection ◦ お手製 template literal • 面白いことができるが、気軽に使うと大変なことに ◦ 乱用、ダメ。ゼッタイ。