mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -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();
|
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.
|
/// 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
|
/// This future resolves when either the value is resolved or the event loop runs to
|
||||||
|
@ -694,38 +730,7 @@ impl JsRuntime {
|
||||||
&mut self,
|
&mut self,
|
||||||
global: v8::Global<v8::Value>,
|
global: v8::Global<v8::Value>,
|
||||||
) -> Result<v8::Global<v8::Value>, Error> {
|
) -> Result<v8::Global<v8::Value>, Error> {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| self.poll_value(&global, cx)).await
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs event loop to completion
|
/// 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]
|
#[tokio::test]
|
||||||
async fn test_resolve_value() {
|
async fn test_resolve_value() {
|
||||||
let mut runtime = JsRuntime::new(Default::default());
|
let mut runtime = JsRuntime::new(Default::default());
|
||||||
|
|
Loading…
Reference in a new issue