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
Added XMLHttpRequest support #50
Conversation
src/webapi/xml_http_request.rs
Outdated
/// Send request on an open connection with the Value that is being sent | ||
/// If using GET it would be Null | ||
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send) | ||
pub fn send(&self, value: Value) { |
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.
Looking at the JS interface I think it would be better to provide multiple versions of this function instead of having it take a catch-all Value
. Perhaps something like this?
fn send( &self );
fn send_with_string( &self, request_body: &str );
fn send_with_bytes( &self, request_body: &[u8] );
src/webapi/xml_http_request.rs
Outdated
#[derive(Debug)] | ||
pub struct XMLHttpRequest { | ||
reference: Reference, | ||
} |
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.
Please make this the same as other Reference
wrappers. (e.g. look at src/webapi/file.rs
for a minimal example) In this case the XMLHttpRequest
derives from IEventTarget
.
src/webapi/xml_http_request.rs
Outdated
/// First argument is the status code, the second argument is the response text | ||
/// Makes use of onreadystatechange: | ||
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange) | ||
pub fn set_callback<F:FnMut(u32, String) + 'static>(&self, callback: F) { |
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.
Instead of ad hoc methods like this I'd prefer to do this through IEventTarget
machinery we already have. (So instead of using this function the user would use add_event_listener
from the IEventTarget
interface.) In which case it would also be nice to have an usage example in the doc comments.
src/webapi/xml_http_request.rs
Outdated
} | ||
} | ||
|
||
/// Open connection with given method (ie GET or POST), and the url to hit |
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.
For every method you expose please take the docs from MDN and lightly edit them as needed, just as in your other PR. (:
src/webapi/xml_http_request.rs
Outdated
var callback = @{callback}; | ||
var xmlHttp = @{reference}; | ||
xmlHttp.onreadystatechange = function() { | ||
if (xmlHttp.readyState == 4) { |
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.
The readyState
should be exposed just like in (for example) file_reader.rs
.
Yeah, I'm planning on doing that tonight or tomorrow. My schedule is a
little weird at the moment cause of vacation. I've got some of it done but
not all of it yet
…On Fri, Dec 29, 2017, 8:21 AM Gabriela Surita ***@***.***> wrote:
@keeslinp <https://github.com/keeslinp> do you plan to address the
changes pointed by @koute <https://github.com/koute>? I'm specially
interested on this feature and would be happy to help if you're ok with
that.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#50 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AC6-bGnWgnkKjoS-CrjVs4fR7pxl9lrvks5tFQMzgaJpZM4RMLY6>
.
|
src/webapi/xml_http_request.rs
Outdated
/// First argument is the status code, the second argument is the response text | ||
/// Makes use of onreadystatechange: | ||
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange) | ||
pub fn set_callback<F:FnMut(u32, String) + 'static>(&self, callback: F) { |
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.
Should this be FnMut? I'm not entirely sure, but if the callback can only resolve once, it should probably be FnOnce
It can resolve more than once. The callback isn't directly connected with a
sent request and so you could send more than once with the same callback.
When I change it to use the event listener machinery I'll do it however it
is done there.
…On Fri, Dec 29, 2017, 12:43 PM Christopher Serr ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> +impl XMLHttpRequest {
+ /// Creates an empty XMLHttpRequest
+ pub fn new() -> XMLHttpRequest {
+ let reference: Reference = js! {
+ var xmlHttp = new XMLHttpRequest();
+ return xmlHttp;
+ }.try_into().unwrap();
+ XMLHttpRequest {
+ reference,
+ }
+ }
+ /// Sets the callback to call once a request completes
+ /// First argument is the status code, the second argument is the response text
+ /// Makes use of onreadystatechange:
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange)
+ pub fn set_callback<F:FnMut(u32, String) + 'static>(&self, callback: F) {
Should this be FnMut? I'm not entirely sure, but if the callback can only
resolve once, it should probably be FnOnce
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#50 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AC6-bAsh4-Sesn149ruOmeWv0fiszy47ks5tFUDMgaJpZM4RMLY6>
.
|
8dd26a7
to
ffd3652
Compare
Should be all done. It now much more reflects the javascript api. Honestly, I don't know if that's necessarily a good thing because it feels a little clunky but I can see how that's less surprising that having to learn a specific api for the callback. |
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.
Looking better!
src/webapi/event.rs
Outdated
/// called when the readystatechange event is fired, | ||
/// that is every time the readyState property of the XMLHttpRequest changes. | ||
/// | ||
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange) |
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 should link to this and have the docs copied from this page:
https://developer.mozilla.org/en-US/docs/Web/Events/readystatechange
src/webapi/xml_http_request.rs
Outdated
use webcore::try_from::TryInto; | ||
|
||
/// XMLHttpRequest object to make http requests | ||
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) |
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.
Please copy the first paragraph from MDN, and also put an extra newline before [(JavaScript docs)]
src/webapi/xml_http_request.rs
Outdated
convertible to EventTarget | ||
} | ||
|
||
/// A number indicating the state of the `XMLHttpRequest`. |
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 Rust it's not a number. (:
src/webapi/xml_http_request.rs
Outdated
Opened, | ||
/// send() has been called, and headers and status are available. | ||
HeadersReceived, | ||
/// Downloading; responseText holds partial data. |
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.
Use Rust names here. (responseText
-> response_text()
)
Also it would be nice to link to those methods you're referring to.
src/webapi/xml_http_request.rs
Outdated
match response { | ||
Value::Null => None, | ||
Value::String(resp) => Some(resp), | ||
_ => None, |
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 should be an unreachable!
.
src/webapi/xml_http_request.rs
Outdated
}; | ||
} | ||
|
||
/// The abort() method aborts the request if it has already been sent. |
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.
You don't have to repeat the method name, e.g. The abort() method
since it should be already obvious to the reader. (:
src/webapi/xml_http_request.rs
Outdated
} | ||
|
||
/// The abort() method aborts the request if it has already been sent. | ||
/// When a request is aborted, its readyState is changed to Done |
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.
readyState
-> link to the ready_state method, status code
-> link to the status method.
src/webapi/xml_http_request.rs
Outdated
|
||
|
||
impl XMLHttpRequest { | ||
/// Create new XMLHttpRequest |
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.
Minor grammar nitpick (this also applies to other doc comments): 'Create' -> 'Creates', and also a dot at the end and put identifiers (like XMLHttpRequest
) inside backticks. (:
src/webapi/xml_http_request.rs
Outdated
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send) | ||
pub fn send(&self) { | ||
js! { | ||
@{self}.send(null); |
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 need to pass the null
here. Just leave the parens empty.
src/webapi/xml_http_request.rs
Outdated
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send) | ||
pub fn send_with_bytes(&self, body: &[u8]) { | ||
js! { | ||
@{self}.send(@{body}); |
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.
Use UnsafeTypedArray
here to make it zero cost.
Haha docs are going to be the death of me :). It's a good learning
experience for me though. I'll make these updates either tonight or
tomorrow night depending how travel goes.
…On Sun, Dec 31, 2017, 3:44 AM Koute ***@***.***> wrote:
***@***.**** requested changes on this pull request.
Looking better!
------------------------------
In src/webapi/event.rs
<#50 (comment)>:
> @@ -1066,6 +1066,27 @@ reference_boilerplate! {
convertible to ProgressRelatedEvent
}
+/// An EventHandler that is called whenever the readyState attribute changes.
+/// The callback is called from the user interface thread.
+/// The XMLHttpRequest.onreadystatechange property contains the event handler to be
+/// called when the readystatechange event is fired,
+/// that is every time the readyState property of the XMLHttpRequest changes.
+///
+/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange)
This should link to this and have the docs copied from this page:
https://developer.mozilla.org/en-US/docs/Web/Events/readystatechange
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> @@ -0,0 +1,129 @@
+use webapi::event_target::{IEventTarget, EventTarget};
+use webcore::value::{
+ Reference,
+ Value,
+};
+use webcore::try_from::TryInto;
+
+/// XMLHttpRequest object to make http requests
+/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
Please copy the first paragraph from MDN, and also put an extra newline
before [(JavaScript docs)]
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + Reference,
+ Value,
+};
+use webcore::try_from::TryInto;
+
+/// XMLHttpRequest object to make http requests
+/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
)
+pub struct XMLHttpRequest( Reference );
+
+reference_boilerplate! {
+ XMLHttpRequest,
+ instanceof XMLHttpRequest
+ convertible to EventTarget
+}
+
+/// A number indicating the state of the `XMLHttpRequest`.
In Rust it's not a number. (:
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + instanceof XMLHttpRequest
+ convertible to EventTarget
+}
+
+/// A number indicating the state of the `XMLHttpRequest`.
+///
+/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState)
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum ReadyState {
+ /// Client has been created. open() not called yet.
+ Unsent,
+ /// open() has been called.
+ Opened,
+ /// send() has been called, and headers and status are available.
+ HeadersReceived,
+ /// Downloading; responseText holds partial data.
Use Rust names here. (responseText -> response_text())
Also it would be nice to link to those methods you're referring to.
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + 3 => Loading,
+ 4 => Done,
+ _ => unreachable!( "Unexpected value of XMLHttpRequest::readyState: {}", state )
+ }
+ }
+
+ /// Returns a DOMString that contains the response to the request as text, or None
+ /// if the request was unsuccessful or has not yet been sent.
+ ///
+ ///[(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText)
+ pub fn response_text(&self) -> Option<String> {
+ let response = js!(return @{self}.responseText;);
+ match response {
+ Value::Null => None,
+ Value::String(resp) => Some(resp),
+ _ => None,
This should be an unreachable!.
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState)
+ pub fn ready_state(&self) -> ReadyState {
+ use self::ReadyState::*;
+ let state: u16 = js!( return @{self}.readyState; ).try_into().unwrap();
+ match state {
+ 0 => Unsent,
+ 1 => Opened,
+ 2 => HeadersReceived,
+ 3 => Loading,
+ 4 => Done,
+ _ => unreachable!( "Unexpected value of XMLHttpRequest::readyState: {}", state )
+ }
+ }
+
+ /// Returns a DOMString that contains the response to the request as text, or None
DOMString -> string
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + }
+
+ /// Returns a DOMString that contains the response to the request as text, or None
+ /// if the request was unsuccessful or has not yet been sent.
+ ///
+ ///[(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText)
+ pub fn response_text(&self) -> Option<String> {
+ let response = js!(return @{self}.responseText;);
+ match response {
+ Value::Null => None,
+ Value::String(resp) => Some(resp),
+ _ => None,
+ }
+ }
+
+ /// Returns an unsigned short with the status of the response of the request.
More detailed docs would be nice. (First paragraph from MDN looks nice,
without the remark that it's an unsigned short since we can already see
that from the prototype.)
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + match response {
+ Value::Null => None,
+ Value::String(resp) => Some(resp),
+ _ => None,
+ }
+ }
+
+ /// Returns an unsigned short with the status of the response of the request.
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/status)
+ pub fn status(&self) -> u16 {
+ js!(return @{self}.status;).try_into().unwrap()
+ }
+
+ /// Open connection with given method (ie GET or POST), and the url to hit
+ /// Async is set for now because it's more ergonimic in rust and it is good form in javascript
"Async is set for now because it's more ergonimic in rust and it is good
form in javascript" -> this seems unnecessary. You can document that it's
asynchronous, but it's not necessary to explain it like this.
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + pub fn send_with_string(&self, body: String) {
+ js! {
+ @{self}.send(@{body});
+ };
+ }
+
+ /// Send request on an open connection with a byte array body
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
+ pub fn send_with_bytes(&self, body: &[u8]) {
+ js! {
+ @{self}.send(@{body});
+ };
+ }
+
+ /// The abort() method aborts the request if it has already been sent.
You don't have to repeat the method name, e.g. The abort() method since
it should be already obvious to the reader. (:
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + js! {
+ @{self}.send(@{body});
+ };
+ }
+
+ /// Send request on an open connection with a byte array body
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
+ pub fn send_with_bytes(&self, body: &[u8]) {
+ js! {
+ @{self}.send(@{body});
+ };
+ }
+
+ /// The abort() method aborts the request if it has already been sent.
+ /// When a request is aborted, its readyState is changed to Done
readyState -> link to the ready_state method, status code -> link to the
status method.
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + Unsent,
+ /// open() has been called.
+ Opened,
+ /// send() has been called, and headers and status are available.
+ HeadersReceived,
+ /// Downloading; responseText holds partial data.
+ Loading,
+ /// The operation is complete.
+ Done,
+}
+
+impl IEventTarget for XMLHttpRequest {}
+
+
+impl XMLHttpRequest {
+ /// Create new XMLHttpRequest
Minor grammar nitpick (this also applies to other doc comments): 'Create'
-> 'Creates', and also a dot at the end and put identifiers (like
XMLHttpRequest) inside backticks. (:
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> + /// Open connection with given method (ie GET or POST), and the url to hit
+ /// Async is set for now because it's more ergonimic in rust and it is good form in javascript
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open)
+ pub fn open(&self, method: &str, url: &str) {
+ js! {
+ @{self}.open(@{method}, @{url}, true);
+ };
+ }
+
+ /// Send request on an open connection with no data
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
+ pub fn send(&self) {
+ js! {
+ @{self}.send(null);
No need to pass the null here. Just leave the parens empty.
------------------------------
In src/webapi/xml_http_request.rs
<#50 (comment)>:
> +
+ /// Send request on an open connection with string body
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
+ pub fn send_with_string(&self, body: String) {
+ js! {
+ @{self}.send(@{body});
+ };
+ }
+
+ /// Send request on an open connection with a byte array body
+ ///
+ /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
+ pub fn send_with_bytes(&self, body: &[u8]) {
+ js! {
+ @{self}.send(@{body});
Use UnsafeTypedArray here to make it zero cost.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#50 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AC6-bGI-widmAN-1HZ3RmbjaUeUohN92ks5tF2WegaJpZM4RMLY6>
.
|
Yeah, sorry for being so pedantic. (: |
I'm sure many future users who are trying to find their way through the
docs are going to thank you :)
…On Sun, Dec 31, 2017, 12:40 PM Koute ***@***.***> wrote:
Haha docs are going to be the death of me :)
Yeah, sorry for being so pedantic. (:
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#50 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AC6-bNJNHUR_TkwsynF_HhKpOnHqx4MTks5tF-MXgaJpZM4RMLY6>
.
|
Should be fixed. Hopefully all the docs are in order now. |
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.
Sorry for the delay!
Two more things I'd like changed.
There are also a few other nitpicks I have, but it's mostly fine so I'm not going to torment you with them. (:
Oh and, I can't physically merge it in as-is due to merge conflicts, so please rebase it on current master. (Basically just squash all of your commits into a single one with git rebase -i <first commit hash that isn't yours>
, then do git fetch --all
, then do git rebase master
, and then you can git push --force
to the branch.)
src/webapi/xml_http_request.rs
Outdated
/// Send request on an open connection with string body | ||
/// | ||
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send) | ||
pub fn send_with_string(&self, body: String) { |
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 should take &str
; no real reason to take String
.
src/webapi/xml_http_request.rs
Outdated
impl XMLHttpRequest { | ||
/// Creates new `XMLHttpRequest`. | ||
pub fn new() -> XMLHttpRequest { | ||
XMLHttpRequest(js!{ |
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.
Actually, you should be able to convert it like this:
js!( return new XMLHttpRequest(); ).try_into().unwrap()
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 I tried that originally and I couldn't get it to work. I wonder if I set something up wrong with the boilerplate macro. I'll try it again tonight, maybe I just made a silly mistake.
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 must have messed up something silly cause it worked fine this time. Thanks.
using reference pattern and event listener instead of custom callback fixed left out comma caused by rebase conflicts Updated docs for XMLHttpRequest Final changes for code review
2f83742
to
cb11159
Compare
Should be all better now :). Thanks for the help! PS: Kudos on breaking a thousand stars, you've done a great job! |
Thanks! (: Anyhow, this mostly looks fine now so I'm going to merge it in. Thank you for the contribution! |
At first, I just made a http_get function on the window that would make a get request and callback with the response, but I figured I might as well just give it a little more substance and create the whole object.
I think that it would be more cost-effective to couple these together so that there is less crossing of he wasm-js boundary and you'd only need to call one function. However, I saw somewhere that this library was trying to maintain low-level access so I figured this would be more flexible for a user. In comparison to the cost of a network request, the cost of crossing the boundary should be negligible.