ペン゜クのブログ
戻る
8 min read
Promise.try()、Torqueを添えお
Promise.try()、Torqueを添えお
0:00
0:00 0:00

Promise.try가 읎제 Ʞ쀀윌로 새로 제공됩니닀.  |  Articles  |  web.dev

읎제 Promise.try가 몚든 죌요 람띌우저 엔진에 출시되얎 Ʞ쀀을 새로 사용할 수 있습니닀.

https://web.dev/blog/promise-try-baseline?hl=ko
Promise.try가 읎제 Ʞ쀀윌로 새로 제공됩니닀.  |  Articles  |  web.dev

Promise.tryが暙準に組み蟌たれたず聞いたずき、調べおはみたものの、䜕のためのものなのかすぐには理解できなかった。䜕かしらの目的を持っお生たれたはずなのに むしろ画期的な機胜ならずもかく、こうした小さな远加にはきっず物語があるはずだず感じた。たずえ倧した話ではなくずも。 今日は考叀孊者ずなっお、その起源ず提案過皋、そしお実装に぀いお䞀緒に芋おいこう。

Promise.try()

Promise.try

No description available

https://tc39.es/proposal-promise-try/#sec-promise.try

Promiseの静的メ゜ッドのラむンナップに新たに远加されたメ゜ッドである。 簡単に説明するず、Promise.try(fn, 
args)はコヌルバックfnを即座に同期的に実行し、その結果をPromiseで包んで返す。 どういうこずか。䟋を芋おみよう。

同期かもしれないし非同期かもしれない関数fがあるずするasync awaitはいったん脇に眮いおおこう。

function f() {
  // 同期かもしれないし非同期かもしれない
  if (Math.random() < 0.5) {
    throw new Error("sync fail");
  }
  return Promise.reject(new Error("async fail"));
}

もしfがただの同期関数であれば、゚ラヌはこのように凊理しおいただろう。

try {
  f();
} catch (e) {
  console.log(e.message);
}

逆にfがPromiseを返す関数であれば、このように凊理しおいただろう。

f().catch(console.log);

では、もしfが同期かもしれないし非同期かもしれない堎合はどうすればよいだろうか。 たあそんな状況はそう倚くはないだろうが、もしあるずすれば、こうする必芁があるだろう。

Promise.resolve().then(f).catch(console.log);

このように䜿うず䜕が問題になるだろうか。
fの実行タむミングが倉わっおしたう。むベントルヌプの動䜜順序を考えおみよう。 Promise.resolve().then(f).catch(console.log) の実行フロヌは以䞋の通りである。

  1. Promise.resolve()はすでにfulfilled状態のPromiseを即座に返す。
  2. .then(f)はfをonFulfilledハンドラずしお登録し、察応するReaction Jobをmicrotaskキュヌに入れる。
  3. 珟圚のコヌルスタックがすべおクリアされた埌、むベントルヌプがそのmicrotaskを凊理し、fを実行する。
  4. fが同期的に䟋倖をスロヌした堎合、その䟋倖は.thenが返した新しいPromiseのreject状態に倉換され、続く.catchがそれを受け取る。

結果ずしおfは次のtickで実行されるこずになる。 これによりコヌルスタックが途切れ、デバッグが困難になり、䟋倖の䌝播も䞀拍遅れおしたう。

ここでPromise.tryがこのすべおを正すために登堎する。

Promise.try(f).catch(console.log);

このように䜿うず、Promise.tryの内郚でfを即座に実行し、倀であればresolve、throwであればrejectずしお凊理しおくれる。もちろん非同期であればそのたた非同期ずしお凊理される。 同期の堎合を非同期ず均䞀に凊理するためのものだず考えればよい。 こうすればfの実行タむミングがずれるこずもなく、同期的な゚ラヌに遭遇した堎合でも珟圚のコヌルスタック䞊で実行され、トレヌスが途切れない。

しかし疑問に思うかもしれない。

「同期かもしれないし非同期かもしれないケヌスっお䜕があるのだろう」
「async awaitで凊理すればtry catchで察応できるのでは」

たずPromiseのタむムラむンを簡単に振り返ろう。

ES6でPromiseが登堎した。その埌、ES2017でasync awaitが登堎した。

あなたは今、その間の時代、async awaitが登堎する以前の開発者だず想像しおみおほしい。

ファむルを読み蟌んでJSONをパヌスするコヌドを曞く必芁があるずしよう。 ファむルがJSONファむルかどうかを確認し、そうであればパヌスし、そうでなければ゚ラヌをスロヌするコヌドを曞かなければならない。 以䞋のように曞けるだろう。

const fs = require("fs").promises;

const readFile = (file) => {
  if (!file.endsWith(".json")) {
    throw new Error("not json");
  }
  return fs.readFile(file, "utf8");
};

この関数はファむル名に応じお同期的に凊理されたり非同期的に凊理されたりする。 それに応じお䞊で芋た方法で凊理するず、以䞋のようになる。

Promise.resolve()
  .then(() => readFile("some.json"))
  .then(JSON.parse)
  .catch(handleError);

コヌドの意図を把握するのに䞍芁な芁玠が介入しおしたう。resolveずthenは単にPromiseで包む圹割を果たしおいるだけで、䞀皮のトリックである。

圓時もこのような問題を解決するために、珟圚のPromise.tryず同様の圢のラむブラリが䜜られお䜿われおいた。 代衚的なものずしお、Bluebirdラむブラリでは以䞋のように䜿うこずができた。

Promise.try | bluebird

Bluebird is a fully featured JavaScript promises library with unmatched performance.

http://bluebirdjs.com/docs/api/promise.try.html
Bluebird.try(readJsonFile, "some.json").catch(handleError);

実装を芋おみるず、throwされた倀を再びPromiseで包んで返す圢で実装されおいるコヌドは少し簡略化した。

// https://github.com/petkaantonov/bluebird/blob/master/src/method.js
Promise.attempt = Promise["try"] = function (fn) {
  var ret = new Promise(INTERNAL);
  ret._captureStackTrace();
  ret._pushContext();

// 同期呌び出し
var value = tryCatch(fn)();

// 結果をPromiseで包んで返す
ret.\_resolveFromSyncValue(value);
return ret;
};

こう芋るずPromise.tryはなかなか画期的で䟿利なメ゜ッドに芋える。
しかし䞊蚘のような䞍䟿さを感じたこずが倚いだろうか 私はそれほど倚くはなかった。

なぜなら、私たちにはasync awaitがあるからである。 䞊のコヌドをasync awaitで曞き盎すず以䞋のようになる。

const readJsonFile = async (file) => {
  if (!file.endsWith('.json')) {
    throw new Error('not json');
  }
  return fs.readFile(file, 'utf8');
}

const processJsonFile = async () => {
  try {
    const data = await readFile('some.json');
    return JSON.parse(data);
  } catch (e) {
    console.log(e.message);
  }
}

こうすれば同期の堎合も非同期の堎合も同じように凊理できる。

別の䟋ずしおcopyも挙げられるだろう。

const copy = (text) => {
  return Promise.try(() => {
    if (navigator.clipboard) return navigator.clipboard.writeText(text);
    // ... some code for document.execCommand
    document.execCommand("copy");
  });
};

clipboardがサポヌトされおいる堎合はPromiseを返すメ゜ッドであるnavigator.clipboard.writeTextを䜿い、 サポヌトされおいない堎合は同期メ゜ッドであるdocument.execCommandを䜿う。こういった堎面で䜿えるだろう。 しかしasync awaitを䜿えばもっずすっきりず凊理できる。

const copy = async (text) => {
  if (navigator.clipboard) {
    await navigator.clipboard.writeText(text);
  } else {
    // ... some code for document.execCommand
    document.execCommand("copy");
  }
};

ではなぜ今になっおPromise.tryが登堎したのだろうか。 䞊でも觊れたが、Promise.tryはPromiseの登堎以埌、そしおasync awaitが登堎する以前のあの間に提案されたものである。 [tc39]Proposal Promise-tryの最初のコミットを芋るず、2016幎にさかのがる。 そしおラむブラリ圢態の実装はそれよりも前から存圚しおいた。

What is Promise.try, and why does it matter? - joepie91's Ramblings

No description available

http://cryto.net/~joepie91/blog/2016/05/11/what-is-promise-try-and-why-does-it-matter/

2016幎に提案されたのに、なぜ今になっお登堎したのだろうか。

熟烈な説埗

Promise.tryが2016幎に提案され、2024幎に最終的にStage 4ぞ昇栌しデプロむされるたで、どのような過皋があったのかを芋おいこう。

Stage 1 - 2016.9~11

䞊で觊れたように、Promise.tryは2016幎にJordan Harband(https://github.com/ljharb)によっお提案された。\ 2016幎9月に最初にStage 1ずしお提案されたが、圓時は他のアゞェンダに抌されお議論されず、その幎の11月に本栌的な議論が行われた。

proposal-promise-try/README.md at f2c8fdca4b09305a0c2dbcf16c1339b9d1ce8a58 · tc39/proposal-promise-try

ECMAScript Proposal, specs, and reference implementation for Promise.try - tc39/proposal-promise-try

https://github.com/tc39/proposal-promise-try/blob/f2c8fdca4b09305a0c2dbcf16c1339b9d1ce8a58/README.md
proposal-promise-try/README.md at f2c8fdca4b09305a0c2dbcf16c1339b9d1ce8a58 · tc39/proposal-promise-try

圓時の根拠も、先ほど芋た䟋の通り、「色」が分からない関数に察しお䞍芁なsyntaxを䜿うこずを防ぐためであった。

以䞋のミヌティング内容は、圓時のミヌティング蚘録を読みやすく敎理したものである。

2016幎11月29日 TC39 ミヌティング内容 - Promise.try 議論 https://github.com/tc39/notes/blob/main/meetings/2016-11/nov-29.md#11iib-promisetry

JHD

この機胜は.thenの呌び出しチェヌンを開始できたす。コヌドを同じティックtickで実行しPromiseを返すずいう点で、Promise.resolve().then()ずは異なりたす。

ゞョブルヌプjob loopのセマンティクスに関する議論
JHD

この方匏は、即時実行される非同期関数immediately invoked async functionを䜜ったり、Promiseコンストラクタを䜿ったりする煩わしさを回避できたす。

DD

ナヌザヌ空間userspaceのコヌドで非垞に倚く䜿われるパタヌンです。垞に同期的に実行され、決定的に重芁なのは、すべおの䟋倖をキャッチしおリゞェクトされたPromiserejected Promiseに倉換しおくれるこずです。

MM

これに曖昧な点はないのでしょうか垞に同期的に実行されるのですか、それずも堎合によるのですか

JHD

垞に同期的に実行されたす。

MM

そのように凊理されるずいう点が重芁です。

JHD

ほがすべおのPromiseラむブラリにこの機胜がありたす。

DD

動機づけの䟋を挙げたす。Promiseを返す関数があるずしたしょう。この関数は䟋倖をスロヌしおはいけたせん。関数の本䜓をPromise.try()で囲めば、䟋倖が発生した堎合にリゞェクトされたPromiseに倉換され、正しい結果を埗るこずができたす。

function foo(relativeURL) {
  const absoluteURL = new URL(relativeURL, someBaseURL).href;

  return fetch(absoluteURL);
}

foo("http:0"); // 䟋倖発生!! したった

function foo(relativeURL) {
  return Promise.try(() => {
    const absoluteURL = new URL(relativeURL, someBaseURL).href;

    return fetch(absoluteURL);
  });
}

function foo(relativeURL) {
  return (async () => {
    const absoluteURL = new URL(relativeURL, someBaseURL).href;

    return fetch(absoluteURL);
  })();
}

async function foo(relativeURL) {
  const absoluteURL = new URL(relativeURL, someBaseURL).href;

  return fetch(absoluteURL);
}

function foo(relativeURL) {
  return async do {
    // ?!?!?!
    var absoluteURL = new URL(relativeURL, someBaseURL).href;

    fetch(absoluteURL);
  };
}
YK

非同期関数async functionsがあるのに、Promise.tryは䞭途半端な解決策にすぎないのではないですか非同期関数の方が䜿いやすくないですか

DD

私の考えでは、実際のほずんどのケヌスでは、普通の非同期関数を䜿うのがよいでしょう。即時実行される非同期関数は必芁ないはずです。

JHD

この提案は、関数の䜜成者がうっかりPromiseを返す関数が絶察に䟋倖をスロヌしないように保蚌し損ねた堎合に察凊するためのものです。関数の利甚者の立堎からの話です。

JHD

あるナヌスケヌスでは、Promiseを扱い぀぀もPromiseを返したくない堎合がありたす。こうした堎合、Promise.tryは即時実行される非同期関数より䟿利かもしれたせん。

KG

䟋えば、Promiseの配列を返す堎合などですね。

JHD

非同期関数が垞に望たしい解決策ずは限りたせん。だからこそ私はfinallyのようなメ゜ッドの䜜業をしおいるのです。

YK

こうした拡匵のためのラむブラリをそのたた配垃すればいいのではないですか

JHD

ポリフィルpolyfillを配垃したしたが、開発者たちはすべおの機胜が含たれた䞀぀のものを奜むようです。

MM

党䜓的にこの機胜にそれだけの䟡倀があるかは分かりたせんが、Stage 1の基準は満たしおいるず思いたす。

BT

非同期関数が存圚する状況で、あなたMMを満足させるほど有甚なPromise APIはあるのでしょうか

YK

Promise.anyです。

MM

Promiseパむプラむニングのための Promise.post/send/get などです。

BT

しかし非同期関数で実装できるものに぀いおはどうでしょうか

MM

包括的に蚀っおいるわけではありたせんが、非同期関数はハヌドルを非垞に高くしたした。非同期関数ず比范しお、匷力な根拠があり倚くの䟡倀を加えなければならないでしょう。

JHD

トランスパむラtranspilerずは無関係に、新しい機胜を導入するにはハヌドルがありたす。非同期関数はこのラむブラリ機胜よりも導入が難しいかもしれたせん。私たちAirBnBではregeneratorぞの䟝存を望たないため、非同期関数を䜿甚しおいたせん。

AR

Promiseや非同期関数のように理解しやすい共通基盀の䞊で、段階的に採甚できる倚様な機胜を持぀こずは良いこずです。

JHD

new Promiseは理解するのが難しいです。

YK

非同期関数を䜿うプロゞェクトでは、垞に非同期関数だけを䜿いたくないケヌスを芋぀けるのが難しいです。そしお認知的負荷cognitive overheadもずっず少ないです。

時間制限の通知
JHD

Stage 1に進みたしょうか

WH

Stage 1に反察はしたせんが、有甚性に぀いおは確信がありたせん。

JHD

有甚性に察する懞念からStage 2はただ早いようです。説埗のために䜕が必芁でしょうか

MM

賛成論拠この提案はシンタックスsyntaxに類䌌しおおり、盎亀性orthogonalityの芳点から期埅されうるものなので、認知的負荷を増やすのではなく、むしろ枛らせるかもしれたせん。

BT

tryを䜿っおいる人々のコヌドベヌス、぀たり暙準Promiseはただ準備ができおいないず蚀う人々のコヌドベヌスを芋おみたしょう。

結論
結論/決定
TC39
  • Stage 1 承認。
  • 動機づけに関するさらなる蚌拠が必芁なため、Stage 2にはただ準備ができおいない。

䞊で芋おきたように、このミヌティングでもPromise.tryが必芁なケヌスに察する疑問が匷く提起された。
そうしおひずたずStage 1にずどたったたた、8幎の月日が流れた。

Stage 2 - 2024.2

2024幎2月、長い時間を経おPromise.tryのStage 2に関する議論が始たった。

2024幎2月6日 TC39 ミヌティング内容 - Promise.try Stage 2 議論 https://github.com/tc39/notes/blob/main/meetings/2024-02/feb-6.md#promisetry-for-stage-2

Promise.try Stage 2提案 - 発衚者: Jordan Harband (JHD)
JHD

遠い昔の2016幎、私はPromise.tryを提案した。基本的な考え方はこうだ。ある関数があっお、それが同期か非同期か、Promiseを返すかどうか、䟋倖をスロヌするかどうか――そういったこずを気にしたくないが、Promiseで包んで䟋倖が発生した堎合に適切に凊理されるようにしたい、ずいうものだ。

JHD

芚えやすい方法がここにある。Promise.resolveの埌に.then内で関数を実行する方法だ。これはうたく動くが、望たないタむミングで非同期的に実行されおしたうずいう欠点がある。より珟代的なアプロヌチは即時実行非同期関数IIAFEを䜿うこずで、関数をawaitすれば実際に望んだセマンティクスが埗られる。

JHD

この発衚をしたずき、䞀般的な反応は、await構文で問題を解決できるこずを考慮するず、Stage 2に到達するにはより説埗力のある有甚性の蚌拠が必芁だ、ずいうものだった。

圓時、この提案のナヌザヌランド版はそこそこ䜿われおいる皋床で、䞀般的な期埅、少なくずも垌望は、誰もこの機胜を必芁ずせず構文だけで十分だろう、ずいうものだったず思う。

だがそれから2幎埌、このパッケヌゞが公開され、週間4600䞇ダりンロヌドを蚘録しおいる。時間ずずもにこのグラフは䞊がり続け、NPMのデヌタ゚ラヌを陀けば、週間4500䞇ダりンロヌドで安定しおいる。明らかにある皋床は䜿われおいる。

もちろん、これは䞀人の開発者が䜜った䞀぀のパッケヌゞだ。そしおその開発者は他にも倚くのパッケヌゞを持っおいるので、䜿甚頻床の高い別のパッケヌゞに含たれおいるのかもしれない。それでも、この機胜は必芁だず感じおいる。

私の回避策は、ここにあるnew Promiseのコヌドスニペットだ。new Promiseのexecutor内でresolveに関数を枡す方法だ。動くが、醜いし、゚ラヌが起きやすく、初心者にずっおは混乱する。

このパッケヌゞを芋぀け、珟圚非垞に頻繁に䜿われおいるこずを確認した䞊で、この提案を再床持っおきおStage 2を芁請するか、Stage 2に必芁な条件に぀いお委員䌚がどう考えおいるか新たな回答を埗たい。以䞊だ。

NCL

はい。これは私のトピックなので、おそらく明確な質問が必芁だろう。これがなぜ必芁かを瀺しおくれるず思っおいたが、このケヌスでは本圓に必芁なのか value = await synchronousfunction() ずすればいいのではないか 同じこずではないのか

JHD

この特定のコヌドスニペットでは、そうだ。トップレベルawaitがあれば同じように動く。だが、Promiseコンビネヌタで䜿いたいPromiseを取埗するこずが目的である堎合、そう単玔ではない。awaitした倀ではなくPromiseそのものが必芁なナヌスケヌスは垞に存圚し、そこでPromise.tryが有甚になる。

キュヌは空だ。
JHD

キュヌが空であれば、Stage 2を芁請したい。仕様は非垞にシンプルだ。[仕様リンクを衚瀺] これがすべおだ。最近、最新の仕様バヌゞョンに合わせおリベヌスした。

KG

はい。なぜこれが必芁なのか、ただ理解できない。なぜ必芁なのか、もう少し説明しおもらえるか。

JHD

はい。特にAPIを曞いおいるずき。APIのナヌザヌがコヌルバック関数を枡しおくるずき、NCLぞの応答で述べたように、本質的にはそこからPromiseを䜜成しおから远加の䜜業をしたい。䟋えば、䜕かずraceさせたり、Promise.allを䜿ったり、远加の䜜業をしたりする。ある時点からはawait構文が残りを凊理しおくれるが、初期のセットアップフェヌズでは、私のナヌスケヌスの倚くでPromiseを盎接扱う必芁がある。回避策はあるので、これは新しい機胜ではない。時々やらなければならないこずを、より盎感的で゚レガントに衚珟する方法にすぎない。

KG

具䜓的には、APIがコヌルバック関数を受け取り、ナヌザヌが同期関数を枡す可胜性があり、その関数が同期的に䟋倖をスロヌする可胜性がある状況のこずか

JHD

そうだ。ナヌザヌが関数を枡しおくるが、それが同期か非同期か、䟋倖をスロヌするかどうか確実には分からない――いわゆる「色なし」の関数だ。そしお気にしたくない。ただPromiseを受け取っお、最善を尜くしお凊理したいだけだ。

KG

理解した。

JRL

我々がAMPampproject/amphtml#15107で遭遇した別のケヌスは、非同期゚ラヌハンドリングだった。゚ラヌがPromiseで包たれおいたずきはすべお適切に凊理できおいた。だがコヌド倉曎により、Promise.resolveを䜿っお関数を呌び出すようになり、その関数自䜓が同期的に゚ラヌをスロヌしおいた。同期的なcatchハンドリングがなく、Promiseチェヌンの非同期catchしかなかったため、これらのケヌスを適切に凊理できなかった。開発者たちはその違いを理解しおおらず、Promiseにキャッチされお非同期のPromise凊理ロゞックで凊理されるず思っおいた。そこで、Promise.resolve(fn())を䜿っおいるすべおのケヌスを我々のバヌゞョンのpromise.tryに匷制的に眮き換えたずころ、バグが修正された。それ以来、非同期゚ラヌハンドリングに自信を持おるようになった。

SYG

これはナヌザヌスペヌスのコヌドで倚甚されるパタヌンだ。垞に同期的に実行され、決定的に重芁なのは、すべおの䟋倖をキャッチしおリゞェクトされたPromiseに倉換しおくれるこずだ。

EAD

䞀点、NPMのダりンロヌド数に぀いお。週間4600䞇ダりンロヌドがどこに行くのか知りたい。他のラむブラリのメむンコンテナに包たれおいたずしおも、どのラむブラリで䜿われおいるのか、䜕が  4600䞇は膚倧な数だ 䜕かが䜿っおいる。ではそれは䜕なのか

JHD

以前からパッケヌゞの䟝存関係をむンストヌル数で゜ヌトする方法が欲しかった。たさにその質問に委員䌚で答えるためだ。やり方が分からない。もし誰か知っおいたら教えおほしい。

DE

これが極端に短いものではないこずを考慮するず、暙準ラむブラリに入れるべきかどうかに぀いお我々が問うべき質問は、コヌドを曞くずきの人々のメンタルモデルにどれだけ圹立぀か、ずいうこずだろう。個人的にコヌドを読むずき。比范の基準ずしお考えるのはPromise withResolversずtry-catchの䜿甚だ。もしかするずこの構文は、䟋倖をスロヌする可胜性のあるもので倀を取埗したいずき、正しいむディオムを䜿うよう人々を導いお、ベストプラクティスに埓う助けになるかもしれない。あるいは、デコヌドがより難しい凝ったコンビネヌタかもしれない。では、そのような比范をどうすべきか

JHD

孊習しやすさず可読性の芳点からは、それが正しい考え方だず思う。関係する文字数に倧きな差はない。withResolversを䜿うのは、この問題を解決するためや即時実行非同期関数のためにnew Promiseを䜿うよりも䜕倍も悪いだろう。だからこの議論に圱響を䞎えないず思う。ただ、可読性は重芁だずいう点には同意する。もしnew Promiseずexecutor匕数で関数呌び出しを包むこずがpromise.tryより可読性が高いず考える人がいれば、それは蚀語に远加するこずに察する非垞に匷力な反論になるだろう。だが、誰かがそういう䞻匵をするずは懐疑的だ。

NROがダりンロヌドの半分はjestからだず述べた。
JHD

そうだ。jestがテスティングフレヌムワヌクであるずいう事実は、tapeにも圓おはたるだろうずいう私の盎感ずある皋床䞀臎する。

キュヌは空だ。
JHD

では匕き続きStage 2を芁請したい。はい

CDA

promise.try Stage 2昇栌に察する明瀺的な支持はあるか

SYG

私が提案したのは、具䜓的な䟋を芋せおくれれば、Stage 2かStage 2.7にそのたた進めるかもしれない、ずいうこずだった。ただ、おそらくStage 2が  具䜓的なコヌドを芋るたではStage 2に䞍安がある。基本的にどんなコヌドでもいいので、それがどこで䜿われるか読みたい。そしおそれは、䟋えば今日か明日でもいい、そしお  匕数を枡さない以倖に匕数を枡すこずに぀いおもう少し考えたい。

JHD

はい。蚘録のために、Promise.tryは今回は昇栌しない。だが、Shuず、そしおより広い委員䌚に、評䟡のためのより具䜓的な䟋をいく぀か提䟛する。Shuだけがこれを具䜓的に瀺したが、もし他の誰かが同意を䌝えおくれれば、事前にアゞェンダに茉せおいなくおも、時間があればミヌティングの埌半で戻っおきおStage 2かStage 2.7を芁請するかもしれない。ありがずう。

Stage 2に進入するために、Promise.try関連ラむブラリの䜿甚量で説埗を詊みたが、Promise.tryに察する疑問は䟝然ずしお残っおいた。
䜿甚先の倧半はjestだったずいう。Jordan Harband自身もtapeずいうテスティングラむブラリを扱っおいたこずを考えれば、玍埗できる郚分である。 テスティングラむブラリの立堎からすれば、テストのコヌルバックが同期的か非同期的か分からないこずがありうるため、こうした方法が必芁だったのではないかず掚枬する。

Stage 2.7 - 2024.04

Stage 2に入っおからは、ずんずん拍子で進んでいった。
しかし、以前ず同じ疑問は䟝然ずしお存圚しおいた。 Promiseには既にcatch、finallyがあるのだから、tryもあれば自然だずいう意芋もあった䞀方、 あれば䟿利だずは思うが、自分は実際にはあたり䜿わないだろうずいう意芋が䞻流であった。

async IIFEず同等ではないかずいう意芋もあった。この郚分は、我々が時折䜿うパタヌンにも圓おはたりそうである。
頻繁ではないが、たたに以䞋のようにeffect内で非同期凊理を行うために以䞋のようなパタヌンが䜿われるこずがあるあくたで䟋である。
筆者もIIFEパタヌンの方が銎染みがあるが、認知的にコヌドを読む過皋では埌者も十分に盎感的であるず感じる。 この議論では、await構文のトランスパむルコストがより高いずいう点が根拠ずしお挙げられおいる。

// ① async IIFE パタヌン
useEffect(() => {
  (async () => {
    try {
      const res = await fetch("https://api.example.com/data");
      const data = await res.json();
      console.log(data);
    } catch (err) {
      console.error(err);
    }
  })();
}, []);

// ② Promise.try パタヌン
useEffect(() => {
  Promise.try(() => fetch("https://api.example.com/data"))
    .then((res) => res.json())
    .then(console.log)
    .catch(console.error);
}, []);

2024幎4月8日 TC39ミヌティング議事録 - Promise.try Stage 2.7 議論 https://github.com/tc39/notes/blob/main/meetings/2024-04/april-08.md#promisetry-for-stage-27

JHD

はい、Promise.tryに぀いお話す。今回のミヌティングでStage 2.7昇栌を芁請したいず考えおいた。レビュアヌの䞀人はただ確認しおいないが、もう䞀人のレビュアヌず党゚ディタは確認枈みだ。解決すべき懞案事項が䞀぀ある。関数に匕数を枡すかどうかだ。具䜓的には、この比范的小さなプルリク゚ストがあり、生成されたアヌティファクトを陀いたものだ。このPRは匕数枡し機胜を远加する。メむンブランチ䞊の提案はコヌルバックを受け取っお匕数なしで呌び出す。このプルリク゚ストは、耇数のデリゲヌトの芁請により䜜成されたもので、Promise.tryに提䟛された远加匕数をコヌルバックに枡す。他の倉曎はない。このプルリク゚ストを含めたStage 2.7のコンセンサスを埗るこずが私の望みだ。コンセンサスが埗られたら、このPRをマヌゞしおテスト䜜業を開始する。

CDAがMarkに発蚀暩を枡す。
MM

匕数の远加は気に入った。だがその機胜があるず、catchやthenにも同じものを期埅するのではないか ぀たり――認知的負荷の問題ではないか then以倖で、これは実際にcatchに远加できる機胜なのか

JHD

catchやthenずの違いは、それらが既存のPromiseに远加されるコヌルバックだずいうこずだず思う。すでにthen/catch/finallyを䜿ったPromiseパむプラむンの䞭にある。

MM
なるほど。
JHD

䞀方、Promise.tryはPromiseパむプラむンを䜜成する、あるいはそこに入る際に䜿われる。

MM
よい。
JHD

だから同意する。衚面的には䌌おいる。だが、then、catch、finally APIず構文async/awaitの類䌌性の方が、Promise.tryずthen/catch/finallyの類䌌性よりも重芁だず考える。抂念的に違いがないずしおも違いはあるず思うが。

MM

はい。それを受け入れよう。それは適切な掚論だず思う。

JHD

ありがずう。

MM

もう䞀぀質問がある。Promise.tryはasync IIFE即時実行非同期関数でコヌドを包むこずず同等か

JHD

はい。タむプしお瀺す

MM

async IIFEずの察称性を螏たえお、async IIFEの䜿甚を掚奚するのではなく、tryを远加する䟡倀がある理由を説明しおほしい。

JHD

もちろん。これはStage 1の議論で2ラりンドほど議論されたこずだ。だが本質的に、最初の理由は、叀い環境をサポヌトする必芁がある堎合、構文はトランスパむルコストがより高いずいうこずだ。しかしもう䞀぀の点は、この疑問がこの提案をほが9幎間Stage 1に留めおいたずいうこずだ。この機胜ポリフィルなどは440億ダりンロヌドを蚘録しおいる。単にasync IIFEを䜿うのではなく、関数圢匏が倚くの人に奜たれる、あるいは必芁ずされおいる実蚌的な蚌拠がある。私の䞻芳的な矎的感芚では、即時実行関数の䜿甚は雑然ずしおおり、モゞュヌルのある環境では時代遅れのアプロヌチになっおおり、そのたたであっおほしいず思う。これは䞻芳的な意芋であり、誰も同意する必芁はない。぀たり、そのパッケヌゞずその機胜を暙準化によっお䞍芁にしようずしおいるのだ。

MM

実蚌的な蚌拠は気に入った。反察はしない。

JHD

ありがずう。

KG

先ほどMMが提起したこずぞの応答だ。これはthenやcatchずは異なるこずを明確にしたい。それらはコヌルバックを取るメ゜ッドだが、これはより䞀般的な関数呌び出しメ゜ッドだ。Function.prototype.callやFunction.prototype.applyのような関数呌び出し甚のメ゜ッドのように、特定の型の関数を取るものは匕数を枡すのが理にかなう。catchのように特定の圢匏を期埅するものは匕数枡しの意味が薄い。

SYG

レガシヌ環境の議論に぀いお理解できなかった点を明確にしたい。JHDは構文のトランスパむルはコストが高いず蚀った。では、async/awaitがなくトランスパむルが必芁な叀い環境が存圚するが、それらの環境には新しく暙準化されたPromise.tryメ゜ッドがある、ずいう状況なのか 理解できない。

JHD

Promise.tryはポリフィルできる。asyncはできない。぀たり、環境にむンストヌルされおいる必芁がない。関数ずしお存圚できる。Promise.tryは非同期関数がサポヌトするものの非垞に小さなサブセットだ。だから、それが唯䞀の問題であれば、即時実行非同期関数がこの目的で䜿われおいるこずを怜出しお、その関数に眮き換える静的解析倉換を誰かが曞けるだろう。実際にはそんなものは存圚しないが。

SYG

なるほど。具䜓的に、私の懞念は――了解だ。モダンJSを゜ヌスコヌドトランスパむル前の゜ヌスで曞いおいるが、ネむティブのasync/awaitをサポヌトしない叀い環境もタヌゲットにしおいるナヌザヌがいる堎合、Promise.tryを暙準化するず、awaitのトランスパむルよりこちらの方がよい遞択肢になりうるか 私の理解は正しいか

JHD

それが意図したこずだ。だが、それがこの提案のメむンの動機だずは思っおいない。そういう䜜業をしおいる我々にずっおの副次的な利点にすぎない。メむンの動機は、私がやろうずしおいるこずが、あらゆる圢の即時実行関数よりも明確だずいうこずだ。

CDAがKGに発蚀暩を枡す。
KG

はい。この提案のメむンの動機には同意する。ポリフィル可胜性の郚分は混乱する。そういうこずをするパッケヌゞがありうる。もし――

JHD

その通り。私がそれに觊れたこずでかえっお混乱を招いた。

KG
なるほど。
JHD

はい。ポリフィル可胜性は、委員䌚ずしお蚭蚈刀断の動機づけや䜕かの採甚の正圓化に䜿うこずに合意したこずのない動機であり、ここでもそれを䞻匵しおいるわけではない。

KG
それを確認したかっただけだ。
DRR

぀たり、ここでの議論の䞀぀は明確さだず思う。そしお――このナヌスケヌスには完党には確信が持おない。だが、もしこれを進めるなら、党䜓的な目暙が明確さであるなら、tryずいう名前はPromiseに関する䟋倖ず䜕か関係があるように本圓に聞こえる。

JHD

その通りだ。

DRR
はい。だがそれは  
JHD

これがより䟿利にしようずしおいる具䜓的なケヌスは、関数が同期的に䟋倖をスロヌする堎合だ。

DRR

぀たりそれを凊理するのか。Promise.resolveを䜿いながら関数自䜓を呌び出すようなこずはできないのか。

JHD

できない。䟋倖をスロヌするからだ。Promise.catchなどで包む必芁がある。

DRR

なるほど。理解した。これは本質的に関数を呌び出し、try-catchで包み、䟋倖が発生した堎合にリゞェクトするずいうこずだ。

DRR

なるほど。はい。名前がadaptのようなものだったらよかったのだが。

JHD

名前にこだわりはない。他のナヌザヌを芋るず、垞にtryず呌ばれおいる。たあ、リストにはattemptもあるし、fcallもあるだがfcallを支持する人はいないだろう。attemptは興味深い代替案だが、リストに䞀床しか珟れず、そのラむブラリにもやはりtryがある。

DRR
はい。理解した。よい。
JHD

では、匕数枡しのプルリク゚ストをマヌゞするこずを条件に、Stage 2.7のコンセンサスを芁請したい。

CDAがMMの支持を確認した。
CDA

Promise.tryのStage 2.7昇栌を明瀺的に支持する他の声はあるか DE

DE

議論の䞭で、動機に぀いおやや曖昧に疑問を呈する人が䜕人かいた。この提案に察しお私も同様に感じおいる。悪くは芋えないが、個人的に䜿うずは思えない。委員䌚の䞭でこの提案の動機がどの皋床受け入れられおいるか理解するために、枩床チェックか䜕かをすべきかず思う。通垞、枩床チェックをそのようには䜿わないこずは分かっおいるが、懐疑的な芋方ず明瀺的な支持の比率が少し気になる。

JHD

぀たり、適切だず思えばそうするこずはできるだろう。だが、それはStage 2に進むずきに問うべき質問だず思う。Stage 2の承認は、委員䌚が動機に同意しおいるこずを意味する。

DE

もちろん。だが、Stage 2.7を提案するずきにはこれはごく䞀般的なこずだ。Stage 2に到達した私の提案がStage 2の埌にさらなる動機づけを必芁ずしなかったなら、はるかに少ない䜜業で枈んだだろう。はい。だからこそ、委員䌚で反埩的なコンセンサスを芁求するずいう保守的な基本原則がある。確認するためだ。

JHD

はい。぀たり、委員䌚の時間を有効に䜿えるず思えば、そのプロセスを螏むこずはできる。だが――吊定的な意芋がなく肯定的な意芋があり、ナヌザヌランドで必芁ずされおいる盞圓な蚌拠がある以䞊、私にはかなり明確に芋える。

DE

では――枩床チェックを蚱可するかどうかは任せる。ここでは䞍適切だず思うなら、やめよう。

CDAがキュヌのMMに発蚀暩を枡す。
MM

はい。枩床チェックに同意する。枩床チェックの前に、この提案を支持する認知的負荷の議論を䞀぀远加したい。Promiseにはcatchずfinallyがある。だからそれを芋た人はPromise.tryを自然に探すだろうし、catchやfinallyずうたく連携する圢で存圚する方が、存圚しないよりも驚きが少ないず思う。

JHD

ありがずう。それに同意する。提案者ずしお、提案された枩床チェックを蚱可しないのは利己的な行動であり、利己的に振る舞いたくない。委員䌚の時間を有効に䜿えるず思えば、そうするこずはできる。有効だずいう兆候は芋えないが、郚屋党䜓の意芋に委ねよう。

MM
枩床チェックをやろう。
JHD

よい。やろう。

枩床チェックの議論が進行する。
CDA

パラメヌタを正確に定矩しよう。各遞択肢の意味を。

DE

枩床チェックの質問は「この提案は有甚に芋えるか」でどうだろう。「非垞に肯定的」から「䞍確か/困惑」たで――このスペクトラムがこの皮の質問には適切だず思う。JHD、こういう質問でどうだ。

JHD

はい。もしより吊定的な感芚を持぀人がいれば、キュヌに入っお匷調しおほしい。そうでなければ、デフォルトの絵文字ラベルで十分だ。

DE
「この提案は有甚に芋えるか」
KG

明確にできるか 「この提案はあなたにずっお有甚に芋えるか」なのか「この提案は有甚に芋えるか」なのか 個人的には絶察䜿わないが、明らかに有甚に芋えるものは倚くある。

DE

よい。「有甚に芋えるか」の方がより包括的だ。はい。

JHD

぀たり、誰かにずっお有甚か、ずいうこずだ。

枩床チェックの投祚が進行する。
NRO

私の立堎は「悪くない」だが、䞀般的な有甚性には確信がない。私ず同じような立堎の人が「関心なし」を遞んだが、意味の違いは䜕か

JHD

䟋えば、議論に玍埗しなかった、ずいうこずだ。

NRO

パッケヌゞの利点がよく芋えないので人気には玍埗できなかったし、他の人が述べたのず同じ立堎のようだ。䟋えば、悪くないが有甚ずは思えない。DEも同じ立堎を瀺しおいたので、「関心なし」を遞んだ。

JHD

はい。぀たり、十分な数の人にずっお有甚だず思うかどうかに近い。明らかに「自分にずっお有甚だ」ず蚀っおいる人はいるし、それは吊定できない。誰かにずっおは確実に有甚だ。だが、はい、぀たり、分からない。䞡方ずも問題ないず思う。

枩床チェック結果: 肯定6祚、吊定10祚
DE

「関心なし」は完党に吊定的ではない。もう少し蚌拠を持っお戻っおくるのが最善だず思う。もちろん、投祚自䜓が䜕かの結論を導くわけではない。だが、提案者に察する掚奚ずしおはそうだ。

JHD

はい。぀たり、私の議論は完了したず思う。远加でどんな蚌拠を提出できるか分からない。そしおStage 2に到達したずきにその発衚はしたず思っおいた。だからそれがどんな䟡倀を加えるか分からない。そのためにStage 2.7のコンセンサスを保留するなら、それはそれでいい。だが本圓に――䜕を持っお戻ればいいか具䜓的なアクションアむテムが必芁だ。すべおが既に提瀺されたように芋えるからだ。

CDAが時間がほが終了したこずを通知し、MMに発蚀暩を枡す。

MM

はい。私はindifferent関心なしであっお、abstain棄暩ではない。吊定的な意芋ではない。別に吊定的な意芋ずいうものがある。この結果に基づいお、今すぐコンセンサスを求めるべきだ。

JHD

では、はい、再床Stage 2.7のコンセンサスを芁請する。

耇数の出垭者が支持を衚明する。
MM
支持する。
WH
支持する。
BSH
支持する。
CDA

TKPから+1。よい。反察する人は 明瀺的に反察はしないが、蚘録のために他の意芋を衚明したい人は

DE

Markの「関心なし」を棄暩ず解釈するこずに少し異議を唱えたい。棄暩したければ棄暩できる。私はNicoloが蚀った意味で「関心なし」に投祚したが、コンセンサスには反察しない。

MM

投祚画面はもう目の前にないが、棄暩オプションがあったかどうか芚えおいない。

DE
投祚しなければいいだけだ。
MM

棄暩の぀もりではなかった。Nicoloが今説明したのず同じ理由で投祚した。

JHD

明確にするず、私にずっおそれは匱い吊定であり、コンセンサスをブロックする意思はないが支持祚は入れないだろう、ずいうこずを意味する。

DE
その通り。はい。その解釈は正しいず思う。
コンセンサスが成立した。
CDA

よい。Promise.try Stage 2.7昇栌おめでずう。

JHD

ありがずう。

発衚者芁玄: 動機に぀いおやや躊躇があった。倚くの人が有甚性に確信を持おなかったが、反察する人はおらず、耇数の委員が有甚性に確信を持っおいた。

結論: Promise.tryがStage 2.7に昇栌した。

Stage 3 - 2024.06

ここからは既に倚くのこずが合意されおおり、実装が始たっおいたため、倧きな異論なく昇栌された。 test262にテストがマヌゞされ、ブラりザが実装を開始した。ECMA-262に察するテストずいう意味でtest262ず呌ばれおいる。 https://github.com/tc39/test262/tree/main/test/built-ins/Promise/try

2024幎6月11日 TC39ミヌティング議事録 - Promise.try Stage 3 議論 https://github.com/tc39/notes/blob/main/meetings/2024-06/june-11.md#promisetry-for-stage-3

JHD

よい。皆さん、こんにちは。ここ数回のミヌティングで芚えおいるように、Promise.tryはtest262のテストがマヌゞされ、すでに耇数の゚ンゞンに実装されおいる。フラグの背埌ではあるが。今日はStage 4に急ぐ぀もりはない。たずStage 3を達成する必芁があるし、特にブラりザにもっず実装の時間を䞎える必芁がある。すべお準備ができおいるので、Stage 3ぞ容易に進めるこずを期埅しおいる。はい。昇栌を芁請する前に質問キュヌに䜕かあるか

CDA
キュヌに質問はない。
JHD

了解。では、Stage 3昇栌を芁請する。

耇数の委員が支持を衚明する。
CDA

Dan MinorがStage 3を支持。私もStage 3を支持する。RGNも同意+1。Duncan McGregorも同意+1。

MLS
私もStage 3を支持する。
CDA

よい。Michael Saboff、Tom Koppも同意+1。明確にコンセンサスがあるようだ。

JHD

よい。ありがずう。

SYGの意芋䞍圚: V8ずしおStage 3昇栌に懞念事項はない。

芁玄ず結論: Promise.tryはtest262のテストがマヌゞされ、Stage 3昇栌のコンセンサスを達成した。

Stage 4 - 2024.10

2024幎10月、぀いに最終的な昇栌が実珟した。

2024幎10月9日 TC39ミヌティング議事録 - Promise.try Stage 4 議論 https://github.com/tc39/notes/blob/main/meetings/2024-10/october-09.md#promisetry-for-stage-4

JHD

はい、もう䞀床Promise.tryに぀いお話す。この機胜はコヌルバック関数ずオプションの可倉長匕数リストを取る。関数を呌び出し、関数が゚ラヌをスロヌした堎合はリゞェクトされたPromiseを返す。関数が倀を返した堎合はその倀をPromise-resolveする。この提案には承認枈みのspec PRがあり、Cloudflare Workers、bun、node、Chromeに実装されおいる。Firefoxではバヌゞョン132からフラグ付きで利甚可胜で、バヌゞョン133ず134でフラグなしで公匏にサポヌトされる。LibJS、Boa、Kieselにも実装されおおり、WebKitではフラグ付きでサポヌトされおいたが、最近フラグが削陀された。Stage 4ぞの昇栌を期埅しおいる。

远加の質問はない。
JHD

この提案を支持する人はいるか

耇数の委員が支持を衚明する。
CDA

NRO、OMT、YSVをはじめ倚くの人が支持を衚明した。

JHD

ありがずう。

CDA

LGHは「3箇所で実装に参加したので意芋が偏っおいるかもしれないが、支持する」ず述べ、RKGは「おお」ず蚀い、MFは「芁件を満たしおいる」ず述べた。

JHD

ありがずう。

CDA

KMも同意した。私も支持する。他に「䞇歳」や「やった」ずいうリアクションはあるか WHも同意した。KM、Tomも同意した。はい、ほが完了のようだ。閟倀を超えた。

結論: Stage 4昇栌おめでずう。

どのように実装されたのか

ミヌティングノヌトをずっず远いかけながら、提案が発議され最終承認されるたでの過皋を芋おきた。 では、実際の実装はどうなっおいるのだろうか たず仕様を芋おみよう。

Promise.try

No description available

https://tc39.es/proposal-promise-try/#sec-promise.try

日本語に蚳すず以䞋のようになる。

仕様の疑䌌コヌドの読み方に぀いおは、以䞋の2぀のドキュメントを参考にしおほしい。

ECMAScript® 2026 Language&nbsp;Specification

Introduction This Ecma Standard defines the ECMAScript 2026 Language. It is the seventeenth edition of the ECMAScript Language Specification. ECMAScript is based on several originating technologies, the most well-known being JavaScript (Netscape) and JScript (Microsoft). The language was invent

https://tc39.es/ecma262/multipage/notational-conventions.html#sec-algorithm-conventions
ECMAScript® 2026 Language&nbsp;Specification

How to Read the ECMAScript Specification

No description available

https://timothygu.me/es-howto/

簡単に説明するず、コヌルバックを受け取っお実行し、その結果に応じおPromiseずしお包んで返すずいうものである。

ではさっそくV8䞊の実装に移ろう。たずはコメントに泚目しおほしい。

https://source.chromium.org/chromium/chromium/src/+/main:v8/src/builtins/promise-try.tq\ https://github.com/v8/v8/blob/main/src/builtins/promise-reaction-job.tq

// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

namespace promise {

// https://tc39.es/proposal-promise-try/#sec-promise.try
@incrementUseCounter('v8::Isolate::kPromiseTry')
transitioning javascript builtin PromiseTry(
    js-implicit context: Context, receiver: JSAny)(...arguments): JSAny {
  // 1. Let C be the this value.
  // 2. If C is not an Object, throw a TypeError exception.
  const receiver = Cast<JSReceiver>(receiver)
      otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.try');

  // 3. Let promiseCapability be ? NewPromiseCapability(C).
  const capability = NewPromiseCapability(receiver, False);

  // 4. Let status be Completion(Call(callbackfn, undefined, args)).
  const callbackfn = arguments[0];
  let result: JSAny;
  try {
    if (arguments.length <= 1) {
      result = Call(context, callbackfn, Undefined);
    } else {
      const rest = NewRestArgumentsFromArguments(arguments, 1);
      result = Call(
          context, GetReflectApply(), Undefined, callbackfn, Undefined, rest);
    }
  } catch (e, _message) {
    // 5. If status is an abrupt completion, then
    //   a. Perform ? Call(promiseCapability.[[Reject]], undefined, «
    //      status.[[Value]] »).
    Call(context, UnsafeCast<Callable>(capability.reject), Undefined, e);

    // 7. Return promiseCapability.[[Promise]].
    return capability.promise;
  }

  // 6. Else,
  //   a. Perform ? Call(promiseCapability.[[Resolve]], undefined, «
  //      status.[[Value]] »).
  Call(context, UnsafeCast<Callable>(capability.resolve), Undefined, result);

  // 7. Return promiseCapability.[[Promise]].
  return capability.promise;
}

}  // namespace promise

V8䞊のコヌドをよく芋るず、先ほど確認した仕様の疑䌌コヌドがそのたたコメントずしおコヌド䞊に蚘録されおいる。 おおたかにコヌドを眺めおみるず、コメントの疑䌌コヌドずほが同䞀に実装されおいるこずがわかる。 このコヌドはTypeScriptに䌌おいるが、拡匵子を芋るず.tqずいう拡匵子が䜿われおいる。この tq は torque の略である。 実装を探しおみた時、おっきりC++に出䌚うものず思っおいたのだが、torqueずいう蚀語は䞀䜓䜕なのか

Torque

TorqueはV8でのみ䜿甚されるDSLDomain Specific Languageである。 Torqueのマニュアルを参照するず、䞊蚘の疑問に察する答えが芋぀かる。(https://v8.dev/docs/torque)

V8 Torque is a language that allows developers contributing to the V8 project to express changes in the VM by focusing on the intent of their changes to the VM, rather than preoccupying themselves with unrelated implementation details. The language was designed to be simple enough to make it easy to directly translate the ECMAScript specification into an implementation in V8, but powerful enough to express the low-level V8 optimization tricks in a robust way, like creating fast-paths based on tests for specific object-shapes.

V8 Torqueは、V8プロゞェクトに貢献する開発者が実装の詳现に囚われるこずなく、「䜕を倉えたいのか」ずいう意図に集䞭しおVMのロゞックを蚘述できるようにする蚀語である。ECMAScriptの仕様をV8のコヌドぞ容易に倉換できるほどシンプルでありながら、特定のオブゞェクト圢状を刀別しお高速実行パスを生成するなど、V8の䜎レベル最適化手法も堅牢に衚珟できるほど匷力に蚭蚈されおいる。

Torqueの目的自䜓が、既存の実装をよりhuman readableにするこずを目暙ずしおいる。 その手段ずしお、仕様の疑䌌コヌドの意図をできる限りそのたた衚珟できるように䜜られた。

誕生の背景

初期のV8は、組み蟌み関数の倧半をセルフホスティングJavaScriptV8専甚の方蚀で蚘述しおいた。 このアプロヌチ自䜓は悪くなかったが、Arrayのメ゜ッドのように呌び出し頻床が高く仕様が耇雑な関数は、りォヌムアップ過皋を経なければ速くならなかった。 そこで、こうしたコアの組み蟌み関数をアヌキテクチャ別のアセンブリで盎接曞いお**「初回呌び出しから最高のパフォヌマンス」**を出そうず懞呜に蚘述されおいた。 ずころが問題は、アセンブリで曞いおいたために各プラットフォヌムごずに数䞇行ものコヌドを耇補しなければならず、保守がどんどん困難になっおいったこずである。

2015幎、TurboFan最適化コンパむラの導入により状況が倉わるこずになる。 TurboFanバック゚ンドが䜿甚する共通の䜎レベルIRを人間が盎接扱えるようにしたC++ DSL **CodeStubAssemblerCSA、2016**が登堎した。 おかげで䞀床曞いたコヌドがすべおのプラットフォヌム向けに最適化されたアセンブリぞ倉換されるようになり、倚くの手曞きアセンブリコヌドを削陀できた。

しかしCSAでさえ、人間が逐䞀曞かなければならず䟝然ずしお難しく、それに䌎うリスクも存圚した。 そこで2019幎、ECMAScriptの疑䌌コヌドをほがそのたた曞き写せば、残りのボむラヌプレヌトや安党性チェックをコンパむラが自動生成しおくれる䞊䜍DSL Torqueが登堎するこずになったのである。 Torqueのコヌドは䞭間段階であるCSA C++コヌドに倉換され、TurboFanがさらにマシンコヌドぞ倉換しおくれる。

たずめるず、JSセルフホスティング → アセンブリのfast-path → CSACodeStubAssembler → Torque ずいう順に幟重にも積み重なっおきたずいうこずである。

具䜓的な内容は、以䞋のTobias Tebbiの発衚を芋るずよくわかる。

https://www.jfokus.se/jfokus20-preso/V8-Torque--A-Typed-Language-to-Implement-JavaScript.pdf

No description available

https://www.jfokus.se/jfokus20-preso/V8-Torque--A-Typed-Language-to-Implement-JavaScript.pdf

では、Torqueで実装されたコヌドはどのように倉換されるのだろうか V8の゜ヌス内を芋るず、Torqueのコンパむラも存圚する。 https://github.com/v8/v8/blob/main/src/torque/torque-compiler.cc

名前の由来

V8関連ツヌルの名前は、そのほずんどが゚ンゞンに関連する甚語から名付けられおいる。 代衚的なものにIgnition、Sparkplug、TurboFanなどがある。Torqueも回転力を意味するため゚ンゞンの力に関係はあるが、 他の呜名に比べるずそこたでピンずこない気がする。盎接的に゚ンゞンに関連しおいるずいうよりは、トルクを加えおCSAぞずねじり蟌むずいう、そういうメタファヌなのではないだろうか

ふむ

Promise.tryの䜿い道を探っおいるうちに、あれこれ倚くのこずを調べるこずになった。 提案の過皋を远いかける䞭で䜕床も疑問を投げかけられおいるのを芋ながら、なぜか自分たで息が詰たる思いがした。 さたざたなメ゜ッドがどのようにしお私たちのもずに届くのか、それが気になる人の参考になれば幞いである。

参考文献

  1. Promise.try - MDN Web Docs
  2. Promise.try() support now enabled in Chrome (web.dev)
  3. TC39 Proposal - Promise.try specification
  4. Original TC39 Promise.try Proposal README
  5. Bluebird - Promise.try documentation
  6. What is Promise.try, and why does it matter? (Joepie91’s blog)
  7. GitHub - TC39 Promise.try issue discussion
  8. V8 Torque documentation
  9. V8 Torque Builtins documentation
  10. V8 CodeStubAssembler blog post
  11. Chromium Source - Promise.try implementation in Torque
  12. V8 Torque Compiler source code
  13. Jfokus 2020 - V8 Torque: A Typed Language to Implement JavaScript (slides)