-
Notifications
You must be signed in to change notification settings - Fork 287
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 test for passing Symbol to JS and fix it for GraalJSRuntime #110
Conversation
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.
Looks good. I'll merge on green.
Rhino fails the new test, cc @josh. And it seems all the conversion is done on the rhino gem side: execjs/lib/execjs/ruby_rhino_runtime.rb Line 35 in 39118e2
So we do we fix it with an explicit |
Upstream issue: rubyjs/therubyrhino#43 |
ExecJS aims at maximum consistency between the various implementations, so yes I think the Rhino adapter should cast symbols to string. That's on us though, it's fine for Rhino to have support for Symbols if it wants to. So I'd close the upstream issue. |
There are already two tests skipped on Rhino: |
I doesn't no. If people wish to use these features they should use the implementation directly, not ExecJS. Now I'm ok with just skipping the test as Rhino is far from a popular backend, but it's not an official feature of ExecJS and we might remove it at any point. |
It's your decision, are you OK with the skip or should I change the Rhino backend for now? I didn't consider it but if Symbol is supported upstream we can remove the workaround here if there wasn't a release in between (and worst case it's redundant but wouldn't change behavior).
All ExecJS backends except therubyrhino support it with this PR and my view is the therubyrhino backend will support it in the future, either from upstream or with the extra |
I'm OK with both, however if you decide to go with the skip, it shouldn't point to the upstream issue because it's not a Rhino issue, it's an ExecJS issue, so it's basically a TODO. |
Alright, I'll just add the change in the backend, and link to the issue there saying it might not be necessary in the future anymore |
I'm not sure we understand each others. Rhino like a few other JS implementation support passing ruby specific types to the JS engine. I very much doubt they'll see this as a bug, I'm 99% sure it's a feature. The reason we don't want to allow this in ExecJS is because many adapters can't support it, e.g. the NodeJS adapter is limited to JSON types because it has to serialize the objects and pass them through STDIN / argv. |
a4efba3
to
7a4f7de
Compare
Right, I didn't think about it like that. MiniRacer, all external runtimes (including But it's true recent JS has Symbols nowadays (although with wildly different semantics, notably they are not unique for a given name), and Rhino doesn't support that and does something different which is to wrap it like any other In any case, I updated the PR to convert in the rhino backend, that seems best for compatibility between runtimes in ExecJS. |
In general ExecJS follows the semantics of JSON.generate & JSON.parse, because that's what the external runtime need to do. |
lib/execjs/ruby_rhino_runtime.rb
Outdated
unbox @rhino_context.eval(properties).call(*args) | ||
# Might no longer be necessary if therubyrhino handles Symbols directly: | ||
# https://github.com/rubyjs/therubyrhino/issues/43 | ||
converted_args = args.map { |arg| Symbol === arg ? arg.to_s : arg } |
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.
This isn't quite enough thoug. args
could be [{foo: 42}]
, so you'd need something that walk down the object graph.
An easy fix could be JSON.parse(JSON.dump(args))
.
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.
Oh, of course, not sure how I missed that.
I'll do that then, it should provide better compatibility for Rhino, at the cost of some performance but then anyway it's not a very common JS runtime nowadays (very old JS version).
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.
Done, I used JSON.parse(JSON.generate(args), create_additions: false)
for consistency with ExternalRuntime, and added tests like this nested example.
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.
at the cost of some performance
Yeah, it's gonna be a bit slower, but ExecJS is really not what you want to use if you want the best performance.
…ubyRhinoRuntime * Add missing require "json" for ExternalRuntime
7a4f7de
to
071dd2d
Compare
@byroot Could you review and merge? :)
@bjfish noticed
barber
and/or Discourse is relying on this.For curiosity I also tried what happens if we pass
Object.new
to JS and on miniracer & node it just passes it as a String with.to_s
likeJSON.dump
does (e.g."#<Object:0x0000000001d05718>"
). On duktape it givesTypeError: cannot convert Object
and on the Graal.js backend it givesTypeError: Unknown how to convert to JS: #<Object:0x1ad8>
.I think the TypeError is good there, JSON just using
to_s
seems rather unexpected in general, so I think let's keep that as-is.