1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ruby.wasmでrequire_relativeを使えるようにできそうだったので ……

Posted at

背景(と先行事例)

ruby.wasmでrequire_relativeを使えるようにしたい
https://speakerdeck.com/ledsun/load-gem-from-browsr

RubyKaigiのレポート読んでたら見つけて、幾つか気になった点があったので(もうできてるみたいだったけど)ちょっと試してみました

requrie_relativeを改変すると標準gemの読込ができなくなる

できるよ

require_relative を上書きした時点で呼び出し元のパスが変わるためエラーになるとのこと
るりまにも

現在のファイルからの相対パスで require します。

って書いてあるし一見できなさそうではあるけれども、これ絶対パス渡してもちゃんと動くので


module Kernel
  alias origin_require_relative require_relative

  def require_relative(path)
    caller_path = caller_locations(1, 1).first.absolute_path || ''
    dir = File.dirname(caller_path)
    file = File.absolute_path(path, dir)

    origin_require_relative(file)
  rescue LoadError
    require_relative_url(path)
  end
end

みたいにして、上書き時点で caller_locations でも使って呼び出し元パスを用意しておけば上書きしても多分ヨシ!
スクリプトのrequire_relative全部置き換えるよりかは素直なんじゃないかな

fetchが非同期関数

fetch?知らない子ですね

…… いやjavascriptはあまり詳しくないというか大分昔に触ったっきりだったのでこう、ね?
XMLHttpRequest とかいう、もはやあまり使われない気がする関数使えば同期/非同期の指定ができるから、こっち使えば行けなくもないでしょというか

結果

require 'js'

module JSRequireRelative
  module_function
  def import(file)
    @pathlist ||= ['']
    file = "#{file}.rb" unless file.end_with?('.rb')
    path = File.absolute_path(file, @pathlist.last)
    @pathlist << File.dirname(path)
    
    path = ".#{path}" if path.start_with?('/')
    evalfile(path)
    @pathlist.pop
  end

  def evalfile(path)
    jsscript = <<~JAVASCRIPT
      const xhr = new XMLHttpRequest()
      xhr.open('GET', '#{path}', false)
      xhr.send()
      return xhr.response
    JAVASCRIPT

    script = JS.eval(jsscript).to_s
    ::TOPLEVEL_BINDING.eval script
  end
end

module Kernel
  alias origin_require_relative require_relative

  def require_relative(path)
    caller_path = caller_locations(1, 1).first.absolute_path || ''
    dir = File.dirname(caller_path)
    file = File.absolute_path(path, dir)
    origin_require_relative(file)
  rescue LoadError
    JSRequireRelative.import(path)
  end
end

実際使うならもうちょっと(特にXHRのとこ)ちゃんと書いた方がいいと思うけど
だいたいこんな感じのをスクリプトの頭に突っ込んでおけば require_relative を(ちょっとお試し程度に)使えるようにできそう
まあWASIにソケットが搭載されれば必要なくなる気もする
require は vender/bundle あたりを対象に同じことする感じになるかな …… ならないかも ……

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?