ruby.wasmでJavaScriptのオブジェクトのプロパティの操作を工夫する - @ledsun blog で考えたJS::Object
に対するパッチをいれてビルドしてみます。
まずテストコードを探しました。
に、テストコードがありました。
def test_method_missing assert_equal "42", JS.eval("return 42;").toString.to_s assert_equal "o", JS.eval("return 'hello';").charAt(4).to_s end
まずはプロパティのショートハンドを入れたいのでassert_equal "5", JS.eval("return 'hello';").length.to_s
こんな感じのアサーションを足すと良さそうです。
テストを実行して失敗させてみます。
rake npm:ruby-head-wasm-wasi:check
を実行します。
def method_missing(sym, *args, &block) if self[sym].typeof == "function" self.call(sym, *args, &block) elsif args.empty? # If no argument, treat as reading a property # Return undefiend if a nonexistent property is read. self.method(:[]).call(sym) else super end end
こんな感じです。
rake npm:ruby-head-wasm-wasi:check
を実行します。
テストが失敗します。
おや?ビルドが必要なのでしょうか?
rake npm:ruby-head-wasm-wasi rake npm:ruby-head-wasm-wasi:check
を実行してみます。 テストが失敗します。 まあ、npmパッケージをビルドしてもRubyスクリプトの部分が変わらないというのはありそうです。
https://github.com/ruby/ruby.wasm/blob/main/CONTRIBUTING.md#building-and-testing-ruby-wasm-wasiをみるともう一手順ありました。
rake build:head-wasm32-unknown-wasi-full-js-debug rake npm:ruby-head-wasm-wasi rake npm:ruby-head-wasm-wasi:check
を実行してみます。
テストが失敗します。
おや?どうすればいいのでしょうか?
ソースコードを眺めてみてもext/js/lib/js.rb
がどうやって、ruby.wasmに取り込まれているのかさっぱりわかりません。
そういえばrake build:head-wasm32-unknown-wasi-full-js-debug
が一瞬で終わっていました。
CRubyをソースコードからビルドし直す必要があるのでしょうか?
rake build:clean rake npm:ruby-head-wasm-wasi rake npm:ruby-head-wasm-wasi:check
を実行してみます。 時間かかるー。
def test_method_missing_with_undefined_method object = JS.eval(<<~JS) return { foo() { return true; } }; JS assert_raise(NoMethodError) { object.bar } end
ですね。なるほど、もともとの動きを変えたところです。 引数のないメソッド呼び出しをプロパティの呼び出しと読み替えたため、NoMethodErrorが出なくなりました。
assert_raise(NoMethodError) { object.bar 0 }
のように引数をつけてあげます。
rake npm:ruby-head-wasm-wasi:check
を実行します。
ハックする手順がわかりました。
もうちょっと早いサイクルで試せると嬉しいです。 まず適当にそれっぽいディレクトリを消してみます。
rm -rf build/wasm32-unknown-wasi/head-wasm32-unknown-wasi-full-js-debug-ext rake npm:ruby-head-wasm-wasi rake npm:ruby-head-wasm-wasi:check
を実行します。 ビルドされないようです。
rm -rf rubies/head-wasm32-unknown-wasi-full-js-debug rake npm:ruby-head-wasm-wasi
を実行します。 エラーがおきました。 中途半端なファイル削除になっているようです。
rm -rf rubies rake npm:ruby-head-wasm-wasi rake npm:ruby-head-wasm-wasi:check
を実行します。 ビルドされました。 あれ?さっきより早いです。
で、やってて気が付いたのはassert_raise(NoMethodError) { object.bar() }
は成り立ちません。
このときはプロパティではなくて、メソッドの呼び出しとして扱って欲しいです。
こんなのは実現出来るのでしょうか?
Rubyの世界からは判定できなさそうに思えます。
20230622 追記
コミットを公開しました。
https://github.com/ledsun/ruby.wasm/commit/bd4cce8f6b88466d5943f6207721d634d2f1c603