mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 08:09:08 -05:00
refactor(core): Extract JsRuntime::poll_value out of JsRuntime::resolve_value (#13461)
This commit is contained in:
parent
5fc4573fae
commit
5e9a6af88d
1 changed files with 82 additions and 32 deletions
114
core/runtime.rs
114
core/runtime.rs
|
@ -686,6 +686,42 @@ impl JsRuntime {
|
|||
scope.perform_microtask_checkpoint();
|
||||
}
|
||||
|
||||
pub fn poll_value(
|
||||
&mut self,
|
||||
global: &v8::Global<v8::Value>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Result<v8::Global<v8::Value>, Error>> {
|
||||
let state = self.poll_event_loop(cx, false);
|
||||
|
||||
let mut scope = self.handle_scope();
|
||||
let local = v8::Local::<v8::Value>::new(&mut scope, global);
|
||||
|
||||
if let Ok(promise) = v8::Local::<v8::Promise>::try_from(local) {
|
||||
match promise.state() {
|
||||
v8::PromiseState::Pending => match state {
|
||||
Poll::Ready(Ok(_)) => {
|
||||
let msg = "Promise resolution is still pending but the event loop has already resolved.";
|
||||
Poll::Ready(Err(generic_error(msg)))
|
||||
}
|
||||
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
v8::PromiseState::Fulfilled => {
|
||||
let value = promise.result(&mut scope);
|
||||
let value_handle = v8::Global::new(&mut scope, value);
|
||||
Poll::Ready(Ok(value_handle))
|
||||
}
|
||||
v8::PromiseState::Rejected => {
|
||||
let exception = promise.result(&mut scope);
|
||||
Poll::Ready(exception_to_err_result(&mut scope, exception, false))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let value_handle = v8::Global::new(&mut scope, local);
|
||||
Poll::Ready(Ok(value_handle))
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits for the given value to resolve while polling the event loop.
|
||||
///
|
||||
/// This future resolves when either the value is resolved or the event loop runs to
|
||||
|
@ -694,38 +730,7 @@ impl JsRuntime {
|
|||
&mut self,
|
||||
global: v8::Global<v8::Value>,
|
||||
) -> Result<v8::Global<v8::Value>, Error> {
|
||||
poll_fn(|cx| {
|
||||
let state = self.poll_event_loop(cx, false);
|
||||
|
||||
let mut scope = self.handle_scope();
|
||||
let local = v8::Local::<v8::Value>::new(&mut scope, &global);
|
||||
|
||||
if let Ok(promise) = v8::Local::<v8::Promise>::try_from(local) {
|
||||
match promise.state() {
|
||||
v8::PromiseState::Pending => match state {
|
||||
Poll::Ready(Ok(_)) => {
|
||||
let msg = "Promise resolution is still pending but the event loop has already resolved.";
|
||||
Poll::Ready(Err(generic_error(msg)))
|
||||
},
|
||||
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
v8::PromiseState::Fulfilled => {
|
||||
let value = promise.result(&mut scope);
|
||||
let value_handle = v8::Global::new(&mut scope, value);
|
||||
Poll::Ready(Ok(value_handle))
|
||||
}
|
||||
v8::PromiseState::Rejected => {
|
||||
let exception = promise.result(&mut scope);
|
||||
Poll::Ready(exception_to_err_result(&mut scope, exception, false))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let value_handle = v8::Global::new(&mut scope, local);
|
||||
Poll::Ready(Ok(value_handle))
|
||||
}
|
||||
})
|
||||
.await
|
||||
poll_fn(|cx| self.poll_value(&global, cx)).await
|
||||
}
|
||||
|
||||
/// Runs event loop to completion
|
||||
|
@ -1859,6 +1864,51 @@ pub mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_poll_value() {
|
||||
run_in_task(|cx| {
|
||||
let mut runtime = JsRuntime::new(Default::default());
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "Promise.resolve(1 + 2)")
|
||||
.unwrap();
|
||||
let v = runtime.poll_value(&value_global, cx);
|
||||
{
|
||||
let scope = &mut runtime.handle_scope();
|
||||
assert!(
|
||||
matches!(v, Poll::Ready(Ok(v)) if v.open(scope).integer_value(scope).unwrap() == 3)
|
||||
);
|
||||
}
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script(
|
||||
"a.js",
|
||||
"Promise.resolve(new Promise(resolve => resolve(2 + 2)))",
|
||||
)
|
||||
.unwrap();
|
||||
let v = runtime.poll_value(&value_global, cx);
|
||||
{
|
||||
let scope = &mut runtime.handle_scope();
|
||||
assert!(
|
||||
matches!(v, Poll::Ready(Ok(v)) if v.open(scope).integer_value(scope).unwrap() == 4)
|
||||
);
|
||||
}
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "Promise.reject(new Error('fail'))")
|
||||
.unwrap();
|
||||
let v = runtime.poll_value(&value_global, cx);
|
||||
assert!(
|
||||
matches!(v, Poll::Ready(Err(e)) if e.downcast_ref::<JsError>().unwrap().message == "Uncaught Error: fail")
|
||||
);
|
||||
|
||||
let value_global = runtime
|
||||
.execute_script("a.js", "new Promise(resolve => {})")
|
||||
.unwrap();
|
||||
let v = runtime.poll_value(&value_global, cx);
|
||||
matches!(v, Poll::Ready(Err(e)) if e.to_string() == "Promise resolution is still pending but the event loop has already resolved.");
|
||||
});
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_resolve_value() {
|
||||
let mut runtime = JsRuntime::new(Default::default());
|
||||
|
|
Loading…
Reference in a new issue