fetchは非同期だった - @ledsun blog でfetchの完了をRuby側で待てなくて、require_relativeの順番の制御が上手く行きませんでした。 ruby.wasmでJS::Object.awaitという関数を見つけました。 名前からするとPromiseを待てそうな関数です。 これを使えばfetchでrequire_relativeが実現できるのでしょうか?
次のようなrequire_relativeの代替え関数を用意します。
function rb_require_relative(relative_feature): Promise<boolean> { const filename = relative_feature.endsWith(".rb") ? relative_feature : `${relative_feature}.rb`; const url = new URL(filename, vm.currentURL); // Prevents multiple loading. if (loadedPathes.has(url.pathname)) { return Promise.resolve(false); } return new Promise((resolve, reject) => { fetch(url).then((response) => { if (response.ok) { response.text().then((text) => { new RubyScriptWithSourceURL(vm, url, text).eval(); resolve(true); }); } resolve(false); }); }); };
これを次のようなRubyの関数で待てれば良さそうです。
require "js" module Kernel def patched_require_relative(relative_feature) JS.global.rb_require_relative(relative_feature).await end end
試して見たところ、そうはならないんですよ。
This method looks like a synchronous method, but it actually runs asynchronously using fibers.
コメントにこう書いてあるとおり、実際には非同期に実行されるので、require_relativeの実行順序は維持できないのでした。