summaryrefslogtreecommitdiff
path: root/core/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/error.rs')
-rw-r--r--core/error.rs67
1 files changed, 52 insertions, 15 deletions
diff --git a/core/error.rs b/core/error.rs
index dc50b4d73..4ee3b9315 100644
--- a/core/error.rs
+++ b/core/error.rs
@@ -326,6 +326,7 @@ impl JsError {
}
if is_instance_of_error(scope, exception) {
+ let v8_exception = exception;
// The exception is a JS Error object.
let exception: v8::Local<v8::Object> = exception.try_into().unwrap();
let cause = get_property(scope, exception, "cause");
@@ -444,24 +445,25 @@ impl JsError {
}
}
- // Read an array of stored errors, this is only defined for `AggregateError`
- let aggregated_errors = get_property(scope, exception, "errors");
- let aggregated_errors: Option<v8::Local<v8::Array>> =
- aggregated_errors.and_then(|a| a.try_into().ok());
-
let mut aggregated: Option<Vec<JsError>> = None;
-
- if let Some(errors) = aggregated_errors {
- if errors.length() > 0 {
- let mut agg = vec![];
- for i in 0..errors.length() {
- let error = errors.get_index(scope, i).unwrap();
- let js_error = Self::from_v8_exception(scope, error);
- agg.push(js_error);
+ if is_aggregate_error(scope, v8_exception) {
+ // Read an array of stored errors, this is only defined for `AggregateError`
+ let aggregated_errors = get_property(scope, exception, "errors");
+ let aggregated_errors: Option<v8::Local<v8::Array>> =
+ aggregated_errors.and_then(|a| a.try_into().ok());
+
+ if let Some(errors) = aggregated_errors {
+ if errors.length() > 0 {
+ let mut agg = vec![];
+ for i in 0..errors.length() {
+ let error = errors.get_index(scope, i).unwrap();
+ let js_error = Self::from_v8_exception(scope, error);
+ agg.push(js_error);
+ }
+ aggregated = Some(agg);
}
- aggregated = Some(agg);
}
- }
+ };
Self {
name: e.name,
@@ -575,6 +577,41 @@ pub(crate) fn is_instance_of_error<'s>(
false
}
+/// Implements `value instanceof primordials.AggregateError` in JS,
+/// by walking the prototype chain, and comparing each links constructor `name` property.
+///
+/// NOTE: There is currently no way to detect `AggregateError` via `rusty_v8`,
+/// as v8 itself doesn't expose `v8__Exception__AggregateError`,
+/// and we cannot create bindings for it. This forces us to rely on `name` inference.
+pub(crate) fn is_aggregate_error<'s>(
+ scope: &mut v8::HandleScope<'s>,
+ value: v8::Local<v8::Value>,
+) -> bool {
+ let mut maybe_prototype = Some(value);
+ while let Some(prototype) = maybe_prototype {
+ if !prototype.is_object() {
+ return false;
+ }
+
+ let prototype = prototype.to_object(scope).unwrap();
+ let prototype_name = match get_property(scope, prototype, "constructor") {
+ Some(constructor) => {
+ let ctor = constructor.to_object(scope).unwrap();
+ get_property(scope, ctor, "name").map(|v| v.to_rust_string_lossy(scope))
+ }
+ None => return false,
+ };
+
+ if prototype_name == Some(String::from("AggregateError")) {
+ return true;
+ }
+
+ maybe_prototype = prototype.get_prototype(scope);
+ }
+
+ false
+}
+
const DATA_URL_ABBREV_THRESHOLD: usize = 150;
pub fn format_file_name(file_name: &str) -> String {