mirror of
https://github.com/servo/servo.git
synced 2025-09-04 03:58:23 +01:00
script: correctly handle indexeddb backend errors (#38740)
Sets the indexeddb request error when the backend errors out. This also matches statements to the spec. Testing: Covered by WPT Fixes: General indexeddb --------- Signed-off-by: Ashwin Naren <arihant2math@gmail.com> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
57f25d0a8a
commit
91b27d98a2
4 changed files with 49 additions and 24 deletions
|
@ -41,7 +41,7 @@ thread_local! {
|
|||
}
|
||||
|
||||
/// Error values that have no equivalent DOMException representation.
|
||||
enum JsEngineError {
|
||||
pub(crate) enum JsEngineError {
|
||||
/// An EMCAScript TypeError.
|
||||
Type(String),
|
||||
/// An ECMAScript RangeError.
|
||||
|
@ -94,7 +94,7 @@ pub(crate) fn throw_dom_exception(
|
|||
/// If possible, create a new DOMException representing the provided error.
|
||||
/// If no such DOMException exists, return a subset of the original error values
|
||||
/// that may need additional handling.
|
||||
fn create_dom_exception(
|
||||
pub(crate) fn create_dom_exception(
|
||||
global: &GlobalScope,
|
||||
result: Error,
|
||||
can_gc: CanGc,
|
||||
|
|
|
@ -220,7 +220,7 @@ impl IDBOpenDBRequest {
|
|||
self.idbrequest.set_result(result);
|
||||
}
|
||||
|
||||
pub fn set_error(&self, error: Error, can_gc: CanGc) {
|
||||
pub fn set_error(&self, error: Option<Error>, can_gc: CanGc) {
|
||||
self.idbrequest.set_error(error, can_gc);
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ impl IDBOpenDBRequest {
|
|||
},
|
||||
Err(dom_exception) => {
|
||||
request.set_result(HandleValue::undefined());
|
||||
request.set_error(dom_exception, CanGc::note());
|
||||
request.set_error(Some(dom_exception), CanGc::note());
|
||||
let event = Event::new(
|
||||
&global,
|
||||
Atom::from("error"),
|
||||
|
|
|
@ -23,13 +23,13 @@ use crate::dom::bindings::codegen::Bindings::IDBRequestBinding::{
|
|||
IDBRequestMethods, IDBRequestReadyState,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::IDBTransactionBinding::IDBTransactionMode;
|
||||
use crate::dom::bindings::error::{Error, Fallible};
|
||||
use crate::dom::bindings::error::{Error, Fallible, create_dom_exception};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
|
||||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||
use crate::dom::bindings::structuredclone;
|
||||
use crate::dom::domexception::{DOMErrorName, DOMException};
|
||||
use crate::dom::domexception::DOMException;
|
||||
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
|
@ -98,11 +98,14 @@ impl From<u64> for IdbResult {
|
|||
}
|
||||
|
||||
impl RequestListener {
|
||||
// https://www.w3.org/TR/IndexedDB-2/#async-execute-request
|
||||
// Implements Step 5.4
|
||||
fn handle_async_request_finished(&self, result: BackendResult<IdbResult>) {
|
||||
let request = self.request.root();
|
||||
let global = request.global();
|
||||
let cx = GlobalScope::get_cx();
|
||||
|
||||
// Substep 1: Set the result of request to result.
|
||||
request.set_ready_state_done();
|
||||
|
||||
let _ac = enter_realm(&*request);
|
||||
|
@ -129,15 +132,21 @@ impl RequestListener {
|
|||
IdbResult::None => {
|
||||
// no-op
|
||||
},
|
||||
IdbResult::Error(_err) => {
|
||||
request.set_result(answer.handle());
|
||||
Self::handle_async_request_error(request, &global);
|
||||
IdbResult::Error(error) => {
|
||||
// Substep 2
|
||||
Self::handle_async_request_error(&global, cx, request, error);
|
||||
return;
|
||||
},
|
||||
}
|
||||
|
||||
// Substep 3.1: Set the result of request to answer.
|
||||
request.set_result(answer.handle());
|
||||
|
||||
// Substep 3.2: Set the error of request to undefined
|
||||
request.set_error(None, CanGc::note());
|
||||
|
||||
// Substep 3.3: Fire a success event at request.
|
||||
// TODO: follow spec here
|
||||
let transaction = request
|
||||
.transaction
|
||||
.get()
|
||||
|
@ -157,15 +166,29 @@ impl RequestListener {
|
|||
.fire(request.upcast(), CanGc::note());
|
||||
transaction.set_active_flag(false);
|
||||
} else {
|
||||
request.set_result(answer.handle());
|
||||
Self::handle_async_request_error(request, &global);
|
||||
// FIXME:(arihant2math) dispatch correct error
|
||||
// Substep 2
|
||||
Self::handle_async_request_error(&global, cx, request, Error::Data);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_async_request_error(request: DomRoot<IDBRequest>, global: &GlobalScope) {
|
||||
// FIXME:(rasviitanen)
|
||||
// Set the error of request to result
|
||||
// https://www.w3.org/TR/IndexedDB-2/#async-execute-request
|
||||
// Implements Step 5.4.2
|
||||
fn handle_async_request_error(
|
||||
global: &GlobalScope,
|
||||
cx: SafeJSContext,
|
||||
request: DomRoot<IDBRequest>,
|
||||
error: Error,
|
||||
) {
|
||||
// Substep 1: Set the result of request to undefined.
|
||||
rooted!(in(*cx) let undefined = UndefinedValue());
|
||||
request.set_result(undefined.handle());
|
||||
|
||||
// Substep 2: Set the error of request to result.
|
||||
request.set_error(Some(error), CanGc::note());
|
||||
|
||||
// Substep 3: Fire an error event at request.
|
||||
// TODO: follow the spec here
|
||||
let transaction = request
|
||||
.transaction
|
||||
.get()
|
||||
|
@ -179,6 +202,7 @@ impl RequestListener {
|
|||
CanGc::note(),
|
||||
);
|
||||
|
||||
// TODO: why does the transaction need to be active?
|
||||
transaction.set_active_flag(true);
|
||||
event
|
||||
.upcast::<Event>()
|
||||
|
@ -227,14 +251,13 @@ impl IDBRequest {
|
|||
self.result.set(result.get());
|
||||
}
|
||||
|
||||
pub fn set_error(&self, error: Error, can_gc: CanGc) {
|
||||
// FIXME:(rasviitanen) Support all error types
|
||||
if let Error::Version = error {
|
||||
self.error.set(Some(&DOMException::new(
|
||||
&self.global(),
|
||||
DOMErrorName::VersionError,
|
||||
can_gc,
|
||||
)));
|
||||
pub fn set_error(&self, error: Option<Error>, can_gc: CanGc) {
|
||||
if let Some(error) = error {
|
||||
if let Ok(exception) = create_dom_exception(&self.global(), error, can_gc) {
|
||||
self.error.set(Some(&exception));
|
||||
}
|
||||
} else {
|
||||
self.error.set(None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
[error-attributes.any.worker.html]
|
||||
expected: TIMEOUT
|
||||
[IDBRequest and IDBTransaction error properties should be DOMExceptions]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[error-attributes.any.html]
|
||||
expected: TIMEOUT
|
||||
[IDBRequest and IDBTransaction error properties should be DOMExceptions]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[error-attributes.any.sharedworker.html]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue