-
Notifications
You must be signed in to change notification settings - Fork 286
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 binding to napi_run_script #692
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.
Thanks for the contribution! This seems very straight forward, but I would like to discuss the API a bit further. Specifically if this method should be marked unsafe
.
src/types/mod.rs
Outdated
@@ -360,6 +360,16 @@ impl JsString { | |||
} | |||
} | |||
|
|||
#[cfg(feature = "napi-1")] | |||
pub fn run_as_script<'a, C: Context<'a>>(self, cx: &mut C) -> JsResult<'a, JsValue> { |
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.
@dherman What do you think about marking this as unsafe
? Even though it's not unsafe by Rust's definition,eval
is a very common exploit vector and it could be helpful to signal to users that only trusted input should be used.
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.
rustls had a similar case: they wanted to add an option that disables cert verification, which was very unsafe, but not rust unsafe
. What they do is put it behind a feature flag and explicitly say "dangerous" on the api.
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 like the idea of adding dangerous
to the function name itself. For example, React has a dangerouslySetInnerHTML
function. We could call this, dangerously_run_script
.
Adding the feature flag seems like additional complexity without any benefit. Unlike with rustls
, the run_script
API will still exist even if we feature flag it because it's part of Node.
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 marking unsafe
when it's not about Rust's safety guarantees is generally considered poor form in the Rust ecosystem, so I agree that's not the best approach. Rather than a prefix, how about a module? Some possibilities:
neon::danger::run_script
neon::advanced::run_script
neon::unchecked::run_script
neon::reflect::run_script
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 should mention, I also agree the feature flag is the wrong approach because it's viral. If a library wants to use the feature they should be able to do it without requiring downstream clients to have to enable the feature flag, and then those clients end up enabling it for everyone anyway, which isn't great either.
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.
Update: @kjvalencik and I spoke this morning, and we came to this suggestion for the naming and documentation:
- It shouldn't be available in any convenience forms (not on
Context
or anywhere else) neon::reflect::eval
is a good name for it: it shows that it's a reflection API, not something to reach for casually, and it connects it to JS'seval
, which is in fact what it is (technically speaking, it's JS's "indirect eval" but you can't implement direct eval as anything other that a syntax in pure JavaScript source code) and also brings along the mindshare from the JS ecosystem about the dangers ofeval
- The API docs should clearly explain that use of
eval
can be a security risk and should not be used casually
@patr0nus How does that sound?
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.
Putting it under neon::reflect
sounds good to me.
However I prefer the name run_script
rather than eval
, since it's a direct binding to napi_run_script
, and as you mentioned, it's not quite the same as eval
in JS. For example, one might assume neon::reflect::eval
can access local variables like JS eval
can.
Also I would suggest the function should accept JsString
instead of AsRef<str>
. If a user wants to be run a script repeatedly, he/she wouldn't want a JsString
to be created every time.
TL;DR: I would prefer the function signature to be:
fn neon::reflect::run_script<'a, 'b, C: Context<'a>>(cx: &mut C, script: Handle<'b, JsString>) -> JsResult<'a, JsValue>
.
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.
In my opinion, the N-API naming is not optimal. It is identical to indirect eval (as defined by the ECMA spec).
Considering direct eval is not possible in a native context, eval seems more appropriate.
Neon already diverges from n-api in a number of places. For example, Root instead of reference.
Additionally, eval
carries the stigma of danger associated with the term, while run_script
does not. I think this is very important.
I like accepting JsString
. This is somewhat outside the scope of this PR, but we could improve the API by adding a ToJsString
trait implemented for Handle<JsString>
, &JsString
, and anything that's AsRef<str>
and making eval
generic.
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.
That seems reasonable. I have pushed the changes.
Though I didn't include the documentation which explains the security risk, as I am not a native speaker, so not really suitable for explaining this kind of serious stuff.
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.
No problem! I am going to be working on API docs next so I can follow up in a future PR with some documentation. Thanks so much for your work!
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.
Edit: (moved this to the appropriate sub-thread)
# Conflicts: # crates/neon-runtime/src/napi/bindings/functions.rs
# Conflicts: # crates/neon-runtime/src/napi/bindings/functions.rs # src/lib.rs
@patr0nus Thanks for the contribution! |
No description provided.