Skip to content
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

Merged
merged 1 commit into from Jan 3, 2018
Merged

Conversation

keeslinp
Copy link
Contributor

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.

/// 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) {
Copy link
Owner

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] );

#[derive(Debug)]
pub struct XMLHttpRequest {
reference: Reference,
}
Copy link
Owner

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.

/// 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) {
Copy link
Owner

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.

}
}

/// Open connection with given method (ie GET or POST), and the url to hit
Copy link
Owner

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. (:

var callback = @{callback};
var xmlHttp = @{reference};
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
Copy link
Owner

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.

@gabisurita
Copy link
Contributor

@keeslinp do you plan to address the changes pointed by @koute? I'm specially interested on this feature and would be happy to help if you're ok with that.

@keeslinp
Copy link
Contributor Author

keeslinp commented Dec 29, 2017 via email

/// 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) {
Copy link

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

@keeslinp
Copy link
Contributor Author

keeslinp commented Dec 29, 2017 via email

@keeslinp
Copy link
Contributor Author

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.

Copy link
Owner

@koute koute left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking better!

/// 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)
Copy link
Owner

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

use webcore::try_from::TryInto;

/// XMLHttpRequest object to make http requests
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
Copy link
Owner

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)]

convertible to EventTarget
}

/// A number indicating the state of the `XMLHttpRequest`.
Copy link
Owner

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. (:

Opened,
/// send() has been called, and headers and status are available.
HeadersReceived,
/// Downloading; responseText holds partial data.
Copy link
Owner

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.

match response {
Value::Null => None,
Value::String(resp) => Some(resp),
_ => None,
Copy link
Owner

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!.

};
}

/// The abort() method aborts the request if it has already been sent.
Copy link
Owner

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. (:

}

/// The abort() method aborts the request if it has already been sent.
/// When a request is aborted, its readyState is changed to Done
Copy link
Owner

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.



impl XMLHttpRequest {
/// Create new XMLHttpRequest
Copy link
Owner

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. (:

/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
pub fn send(&self) {
js! {
@{self}.send(null);
Copy link
Owner

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.

/// [(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});
Copy link
Owner

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.

@keeslinp
Copy link
Contributor Author

keeslinp commented Dec 31, 2017 via email

@koute
Copy link
Owner

koute commented Dec 31, 2017

Haha docs are going to be the death of me :)

Yeah, sorry for being so pedantic. (:

@keeslinp
Copy link
Contributor Author

keeslinp commented Dec 31, 2017 via email

@keeslinp
Copy link
Contributor Author

Should be fixed. Hopefully all the docs are in order now.

Copy link
Owner

@koute koute left a 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.)

/// 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) {
Copy link
Owner

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.

impl XMLHttpRequest {
/// Creates new `XMLHttpRequest`.
pub fn new() -> XMLHttpRequest {
XMLHttpRequest(js!{
Copy link
Owner

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()

Copy link
Contributor Author

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.

Copy link
Contributor Author

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
@keeslinp
Copy link
Contributor Author

keeslinp commented Jan 3, 2018

Should be all better now :). Thanks for the help!

PS: Kudos on breaking a thousand stars, you've done a great job!

@koute
Copy link
Owner

koute commented Jan 3, 2018

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!

@koute koute merged commit 7bf0d86 into koute:master Jan 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants