-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RequireRemote#load to load external Ruby scripts from server #292
Conversation
8fd3180
to
bb03907
Compare
37122ad
to
0629074
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on the feature and sorry for not responding for a while 🙇
Several major comments:
- Can we use another name for this feature to avoid patching
require_relative
? The method is already patched by several places and I don't want to introduce new complexities here. How aboutrequire_remote
? - I'd like to make this feature opt-in since
fetch
is a part of Web API and not generally available on non-Web JS runtimes. Could you removerequire_relative "js/loader.rb"
statement from js.rb and let users explicitly require the file byrequire "js/loader"
? - What happens if "./foo.rb" is redirected to "./bar.rb" at HTTP level and a user tries to load both? This is similar to file system symlink with
require_relative
and it loads only one of them. - I think,
loader
is a little bit too general word. To express it loads remote contents, how aboutjs/remote_loader.rb
, orjs/require_remote.rb
?
Thank you for your comment. I will answer my current thoughts.
I want to run Ruby scripts that work with CRuby in ruby.wasm without modification. Therefore, I would be happy if However, considering that 'require' will be replaced in the future, a name other than
I think it is a reasonable idea. I will correct it.
The current implementation does not handle redirect responses. If a redirect response is returned, it simply fails. Before that, there is a missing implementation that returns false without loading when
Okay, I will rename the Loader. If you have any ideas, please let me know again. |
How about |
f576fe8
to
8eebd6c
Compare
95e7afe
to
9a66904
Compare
If you face build stuck on your local, please rebase upon the latest main 🙏 |
Thanks for letting me know. I was stuck in the following part of the build and it has been resolved.
|
packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/browser-script.spec.ts
Outdated
Show resolved
Hide resolved
776be0c
to
3de3b98
Compare
78f9a70
to
ac43be2
Compare
ac43be2
to
1923112
Compare
8ea928e
to
af4a56d
Compare
Users use JS::RequireRemote#load. The user uses this method to replace the require_relative method. Fix some test codes. - Extract a custom router for integration tests - Split integration test files - Files the body returned by the proxy server
af4a56d
to
115dea3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind adding unit test also to cover more cases? I wonder what should happen for the following case:
.
├── lib
│ ├── a.rb -- require_relative "b.rb"
│ └── b.rb
└── main.rb -- require_relative "lib/a.rb"
Is the current implementation able to load b.rb
well?
packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/js-require-remote.spec.ts
Outdated
Show resolved
Hide resolved
9e0f1f7
to
45755c4
Compare
Added test case to run require_relative recursively. |
|
||
# Return a URL object of JavaScript. | ||
def resolve(relative_filepath) | ||
JS.global[:URL].new relative_filepath, @url_stack.last |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to carefully handle relative path -> absolute path resolution here. IIUC JavaScript's new URL(path, base)
does not behave as we expect for Kernel#require_relative
(and also File.expand_path
).
Here is an example:
path, base |
File.expand_path(path, base) |
new URL(path, "https://example.com" + base) |
---|---|---|
path="b.rb", base="/lib" | /lib/b.rb |
https://example.com/b.rb |
path="./b.rb", base="/lib" | /lib/b.rb |
https://example.com/lib/b.rb |
I think the test suite of File.expand_path
would be helpful for you to see what should be cared https://github.com/ruby/ruby/blob/master/spec/ruby/core/file/expand_path_spec.rb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this behavior of the JavaScript's URL constructor is as expected.
In most cases, I assume that the first value for base
is the URL of an HTML file, such as http://exapmle.com/index.html, or a URL such as http://exapmle.com/index without the extension.
Also, once the ruby script is loaded, the base
value will be the URL of the ruby script, such as http://exapmle.com/a.rb.
So we want the string after the last /
in the base
value to be ignored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok. I misunderstood the second argument. If the second argument is always a URL to a file, then it makes sense to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, unit tests covering this area would be preferable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote unit testsfor JS::RequireRemote::URLResolver.
Please let me know if there are any tests that you think we should add.
Motivation
To run a ruby.wasm application consisting of multiple Ruby scripts, the developer needs to enumerate multiple Ruby scripts.
Like below:
I want to automatically resolve dependencies of Ruby scripts according to the definition of require_relative.
In
main.rb
:In
lib_a.rb
Feature
This pull request provides
RequireRemote#load
method.RequireRemote#load
loads Ruby scripts from server.This is used to emulate
require_relative
.The simplest expamle is below:
The argument of the
RequireRemote#load
method is treated as a relative URL, and the dependent ruby script is fetched from that URL.For example,
RequireRemote#load 'lib_a'
will fetch the script from the URL./lib_a.rb
.