-
Notifications
You must be signed in to change notification settings - Fork 177
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
Adding in Promises #103
Merged
Merged
Adding in Promises #103
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
3f1d716
Initial work on adding in Promises
Pauan 1b00354
Fixing minor nit
Pauan f605bab
Major refactoring
Pauan ebaaa35
Changing the done method to no longer return a new Promise
Pauan f2ab6d8
Adding in promisify method
Pauan 61cb604
Changing to une unsync::oneshot
Pauan bc3809a
Removing Box from PromiseFuture
Pauan b656075
Initial work on the Promise Executor
Pauan 7cb66f9
Adding in promise example
Pauan f416d96
Various cleanup
Pauan 5c479e4
Adding in documentation
Pauan 244701a
Removing some unused code
Pauan 2a3385f
Renaming JSError to Error
Pauan eb30017
Adding in copyright license and attribution
Pauan a256a72
Adding in links to the official spec
Pauan 73fd2a6
Fixing erroneous documentation
Pauan d598941
Fixing minor nit
Pauan 13bebf8
Adding in spawn_print function
Pauan 1ab6c2c
Changing the promise example to use spawn_print
Pauan 56eafa1
Removing PromiseFuture::spawn_print
Pauan 405b3b6
Fix Resubmission Panic in Executor
CryZe 8bd5ba7
Minor refactoring of promise_executor.rs
Pauan a344b2e
Adding in tests for the Executor, and also fixing a deadlock with the…
Pauan 560bcc1
Fixing memory unsafety
Pauan b100726
Adding in some code testing for panics
Pauan 79d6c0b
Removing setTimeout from the Executor, it also now ignores multiple c…
Pauan 7c8bd26
Renaming promisify to convert
Pauan 410cca6
Adding in TODO note
Pauan f8b0118
Alternative executor implementation
Diggsey 7520965
Reorder clearing of `is_queued` to optimize notifying finished tasks
Diggsey 61f91aa
Adding in RefCell example
Pauan 50a456e
Fixing nits
Pauan 48924f9
Enabling the RefCell example
Pauan 329a6e3
Fixing minor nit
Pauan eef311b
Changing to use the new ReferenceType deriving
Pauan 73d9f85
Fixing minor nit
Pauan 960f737
Changing PromiseFuture to allow for any type for the error
Pauan 4475f8b
Renaming Promise::convert to Promise::from_thenable
Pauan ef37ec4
Minor improvement to the docs
Pauan eef539d
Fixing the cfg-gating for futures
Pauan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[package] | ||
name = "promise" | ||
version = "0.1.0" | ||
authors = ["Pauan <pcxunlimited@gmail.com>"] | ||
|
||
[dependencies] | ||
stdweb = { path = "../.." } | ||
futures = "0.1.18" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
#[macro_use] | ||
extern crate stdweb; | ||
extern crate futures; | ||
|
||
use futures::Future; | ||
use stdweb::unstable::{TryInto}; | ||
use stdweb::web::error::Error; | ||
use stdweb::{Null, Promise, PromiseFuture}; | ||
use std::rc::Rc; | ||
use std::cell::RefCell; | ||
use futures::{Poll, Async}; | ||
use futures::task::{current, Task}; | ||
|
||
|
||
fn log( a: &str ) { | ||
js! { @(no_return) | ||
console.log( @{a} ); | ||
} | ||
} | ||
|
||
|
||
fn test_error_conversion() { | ||
let a: PromiseFuture< Null, String > = js!( return Promise.reject( "hi!" ); ).try_into().unwrap(); | ||
|
||
PromiseFuture::spawn( | ||
a.map( |_| () ).map_err( |x| { | ||
log( &format!( "String error: {:#?}", x ) ); | ||
} ) | ||
); | ||
|
||
let _a: PromiseFuture< Null, Error > = js!( return Promise.resolve( null ); ).try_into().unwrap(); | ||
log( "Null works" ); | ||
|
||
let _a: PromiseFuture< Null, Error > = js!( return Promise.reject( new Error( "hi!" ) ); ).try_into().unwrap(); | ||
log( "Error works" ); | ||
|
||
//let _a: PromiseFuture< Null, SyntaxError > = js!( return Promise.reject( new Error( "hi!" ) ); ).try_into().unwrap(); | ||
//log( "Error conversion fails" ); | ||
} | ||
|
||
|
||
fn test_refcell() { | ||
struct TaskA { | ||
shared_state: Rc<RefCell<u32>>, | ||
task_b: Task, | ||
} | ||
|
||
impl Future for TaskA { | ||
type Item = (); | ||
type Error = (); | ||
|
||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||
js! { console.log("Poll TaskA"); } | ||
|
||
let foo = self.shared_state.borrow_mut(); | ||
|
||
js! { console.log(@{format!("TaskA 1: {:#?}", foo)}); } | ||
|
||
self.task_b.notify(); | ||
|
||
js! { console.log(@{format!("TaskA 2: {:#?}", foo)}); } | ||
|
||
Ok(Async::NotReady) | ||
} | ||
} | ||
|
||
struct TaskB { | ||
shared_state: Rc<RefCell<u32>>, | ||
initialized: bool, | ||
} | ||
|
||
impl Future for TaskB { | ||
type Item = (); | ||
type Error = (); | ||
|
||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||
js! { console.log("Poll TaskB"); } | ||
|
||
if !self.initialized { | ||
self.initialized = true; | ||
|
||
let task_b = current(); | ||
|
||
let foo = self.shared_state.borrow(); | ||
|
||
js! { console.log(@{format!("TaskB 1: {:#?}", foo)}); } | ||
|
||
PromiseFuture::spawn(TaskA { | ||
shared_state: self.shared_state.clone(), | ||
task_b: task_b, | ||
}); | ||
} | ||
|
||
let foo = self.shared_state.borrow(); | ||
|
||
js! { console.log(@{format!("TaskB 1: {:#?}", foo)}); } | ||
|
||
Ok(Async::NotReady) | ||
} | ||
} | ||
|
||
PromiseFuture::spawn(TaskB { | ||
shared_state: Rc::new(RefCell::new(0)), | ||
initialized: false | ||
}); | ||
} | ||
|
||
|
||
fn test_panic() { | ||
let promise: Promise = js!( return Promise.resolve(null); ).try_into().unwrap(); | ||
|
||
promise.done( |result: Result< Null, Error >| { | ||
log( &format!( "Promise result: {:#?}", result ) ); | ||
panic!( "Testing panic!" ); | ||
} ); | ||
} | ||
|
||
|
||
fn test_notify() { | ||
struct MyFuture { | ||
polls: u32, | ||
count: u32, | ||
done: bool, | ||
receiver: futures::unsync::oneshot::Receiver< () >, | ||
} | ||
|
||
impl MyFuture { | ||
fn new( count: u32 ) -> Self { | ||
let ( sender, receiver ) = futures::unsync::oneshot::channel(); | ||
|
||
let callback = || { | ||
log( "setTimeout done" ); | ||
|
||
log( &format!("Sending {:#?}", sender.send( () ) ) ); | ||
}; | ||
|
||
log( "setTimeout started" ); | ||
|
||
js! { @(no_return) | ||
setTimeout( function () { | ||
@{stdweb::Once( callback )}(); | ||
}, 1000 ); | ||
} | ||
|
||
Self { | ||
polls: 0, | ||
count: count, | ||
done: false, | ||
receiver, | ||
} | ||
} | ||
} | ||
|
||
impl Future for MyFuture { | ||
type Item = u32; | ||
type Error = (); | ||
|
||
fn poll( &mut self ) -> futures::Poll< Self::Item, Self::Error > { | ||
self.polls += 1; | ||
|
||
if !self.done { | ||
match self.receiver.poll() { | ||
Ok( futures::Async::Ready( () ) ) => self.done = true, | ||
|
||
Ok( futures::Async::NotReady ) => {}, | ||
|
||
Err( _ ) => self.done = true, | ||
} | ||
} | ||
|
||
if self.done { | ||
if self.count == 0 { | ||
Ok( futures::Async::Ready( self.polls ) ) | ||
|
||
} else { | ||
self.count -= 1; | ||
|
||
let task = futures::task::current(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
task.notify(); | ||
|
||
Ok( futures::Async::NotReady ) | ||
} | ||
|
||
} else { | ||
Ok( futures::Async::NotReady ) | ||
} | ||
} | ||
} | ||
|
||
PromiseFuture::spawn( | ||
MyFuture::new( 5 ).map( |x| { | ||
log( &format!( "MyFuture count: {}", x ) ); | ||
assert_eq!( x, 7 ); | ||
} ) | ||
); | ||
} | ||
|
||
|
||
fn test_timeout() { | ||
fn sleep( ms: u32 ) -> PromiseFuture< Null, Error > { | ||
js!( return new Promise( function ( success, failure ) { | ||
setTimeout( function () { | ||
success( null ); | ||
}, @{ms} ); | ||
} ); ).try_into().unwrap() | ||
} | ||
|
||
PromiseFuture::spawn( | ||
sleep( 2000 ).inspect( |_| log( "Timeout 1 done!") ).join( | ||
sleep( 2000 ).inspect( |_| log( "Timeout 2 done!" ) ) ) | ||
.and_then( |_| | ||
sleep( 1000 ).inspect( |_| log( "Timeout 3 done!") ) ) | ||
.and_then( |_| | ||
futures::future::err( Error::new( "Testing error!" ) ) ) | ||
.map_err( |e| e.print() ) | ||
); | ||
} | ||
|
||
|
||
fn main() { | ||
stdweb::initialize(); | ||
|
||
test_refcell(); | ||
test_panic(); | ||
test_notify(); | ||
test_timeout(); | ||
test_error_conversion(); | ||
|
||
stdweb::event_loop(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Could we remove this method?
I understand the need to have convenience methods, but I'd prefer if we'd just wrap
console.error
itself so that you could doconsole::error(e)
.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's fair, though I had kind of figured that
console.error(e)
was a placeholder, and we might implement better error handling in the future, in which case havinge.print()
would be nice. But I don't have a particularly strong opinion about it, so I don't mind removing theprint
method.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.
Since we don't currently have a
console::error
function, I'd rather leave this in for now. Afterwards I'll make another pull request which adds inconsole::error
and removesprint