mirror of
https://github.com/servo/servo.git
synced 2025-09-10 06:58:21 +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.
|
/// Error values that have no equivalent DOMException representation.
|
||||||
enum JsEngineError {
|
pub(crate) enum JsEngineError {
|
||||||
/// An EMCAScript TypeError.
|
/// An EMCAScript TypeError.
|
||||||
Type(String),
|
Type(String),
|
||||||
/// An ECMAScript RangeError.
|
/// An ECMAScript RangeError.
|
||||||
|
@ -94,7 +94,7 @@ pub(crate) fn throw_dom_exception(
|
||||||
/// If possible, create a new DOMException representing the provided error.
|
/// If possible, create a new DOMException representing the provided error.
|
||||||
/// If no such DOMException exists, return a subset of the original error values
|
/// If no such DOMException exists, return a subset of the original error values
|
||||||
/// that may need additional handling.
|
/// that may need additional handling.
|
||||||
fn create_dom_exception(
|
pub(crate) fn create_dom_exception(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
result: Error,
|
result: Error,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
|
|
|
@ -220,7 +220,7 @@ impl IDBOpenDBRequest {
|
||||||
self.idbrequest.set_result(result);
|
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);
|
self.idbrequest.set_error(error, can_gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ impl IDBOpenDBRequest {
|
||||||
},
|
},
|
||||||
Err(dom_exception) => {
|
Err(dom_exception) => {
|
||||||
request.set_result(HandleValue::undefined());
|
request.set_result(HandleValue::undefined());
|
||||||
request.set_error(dom_exception, CanGc::note());
|
request.set_error(Some(dom_exception), CanGc::note());
|
||||||
let event = Event::new(
|
let event = Event::new(
|
||||||
&global,
|
&global,
|
||||||
Atom::from("error"),
|
Atom::from("error"),
|
||||||
|
|
|
@ -23,13 +23,13 @@ use crate::dom::bindings::codegen::Bindings::IDBRequestBinding::{
|
||||||
IDBRequestMethods, IDBRequestReadyState,
|
IDBRequestMethods, IDBRequestReadyState,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::IDBTransactionBinding::IDBTransactionMode;
|
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::inheritance::Castable;
|
||||||
use crate::dom::bindings::refcounted::Trusted;
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
|
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||||
use crate::dom::bindings::structuredclone;
|
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::event::{Event, EventBubbles, EventCancelable};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
@ -98,11 +98,14 @@ impl From<u64> for IdbResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestListener {
|
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>) {
|
fn handle_async_request_finished(&self, result: BackendResult<IdbResult>) {
|
||||||
let request = self.request.root();
|
let request = self.request.root();
|
||||||
let global = request.global();
|
let global = request.global();
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
|
|
||||||
|
// Substep 1: Set the result of request to result.
|
||||||
request.set_ready_state_done();
|
request.set_ready_state_done();
|
||||||
|
|
||||||
let _ac = enter_realm(&*request);
|
let _ac = enter_realm(&*request);
|
||||||
|
@ -129,15 +132,21 @@ impl RequestListener {
|
||||||
IdbResult::None => {
|
IdbResult::None => {
|
||||||
// no-op
|
// no-op
|
||||||
},
|
},
|
||||||
IdbResult::Error(_err) => {
|
IdbResult::Error(error) => {
|
||||||
request.set_result(answer.handle());
|
// Substep 2
|
||||||
Self::handle_async_request_error(request, &global);
|
Self::handle_async_request_error(&global, cx, request, error);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Substep 3.1: Set the result of request to answer.
|
||||||
request.set_result(answer.handle());
|
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
|
let transaction = request
|
||||||
.transaction
|
.transaction
|
||||||
.get()
|
.get()
|
||||||
|
@ -157,15 +166,29 @@ impl RequestListener {
|
||||||
.fire(request.upcast(), CanGc::note());
|
.fire(request.upcast(), CanGc::note());
|
||||||
transaction.set_active_flag(false);
|
transaction.set_active_flag(false);
|
||||||
} else {
|
} else {
|
||||||
request.set_result(answer.handle());
|
// FIXME:(arihant2math) dispatch correct error
|
||||||
Self::handle_async_request_error(request, &global);
|
// Substep 2
|
||||||
|
Self::handle_async_request_error(&global, cx, request, Error::Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_async_request_error(request: DomRoot<IDBRequest>, global: &GlobalScope) {
|
// https://www.w3.org/TR/IndexedDB-2/#async-execute-request
|
||||||
// FIXME:(rasviitanen)
|
// Implements Step 5.4.2
|
||||||
// Set the error of request to result
|
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
|
let transaction = request
|
||||||
.transaction
|
.transaction
|
||||||
.get()
|
.get()
|
||||||
|
@ -179,6 +202,7 @@ impl RequestListener {
|
||||||
CanGc::note(),
|
CanGc::note(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: why does the transaction need to be active?
|
||||||
transaction.set_active_flag(true);
|
transaction.set_active_flag(true);
|
||||||
event
|
event
|
||||||
.upcast::<Event>()
|
.upcast::<Event>()
|
||||||
|
@ -227,14 +251,13 @@ impl IDBRequest {
|
||||||
self.result.set(result.get());
|
self.result.set(result.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_error(&self, error: Error, can_gc: CanGc) {
|
pub fn set_error(&self, error: Option<Error>, can_gc: CanGc) {
|
||||||
// FIXME:(rasviitanen) Support all error types
|
if let Some(error) = error {
|
||||||
if let Error::Version = error {
|
if let Ok(exception) = create_dom_exception(&self.global(), error, can_gc) {
|
||||||
self.error.set(Some(&DOMException::new(
|
self.error.set(Some(&exception));
|
||||||
&self.global(),
|
}
|
||||||
DOMErrorName::VersionError,
|
} else {
|
||||||
can_gc,
|
self.error.set(None);
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
[error-attributes.any.worker.html]
|
[error-attributes.any.worker.html]
|
||||||
|
expected: TIMEOUT
|
||||||
[IDBRequest and IDBTransaction error properties should be DOMExceptions]
|
[IDBRequest and IDBTransaction error properties should be DOMExceptions]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
||||||
[error-attributes.any.html]
|
[error-attributes.any.html]
|
||||||
|
expected: TIMEOUT
|
||||||
[IDBRequest and IDBTransaction error properties should be DOMExceptions]
|
[IDBRequest and IDBTransaction error properties should be DOMExceptions]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
||||||
[error-attributes.any.sharedworker.html]
|
[error-attributes.any.sharedworker.html]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue