summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorAaron O'Mullan <aaron.omullan@gmail.com>2021-05-03 17:30:41 +0200
committerGitHub <noreply@github.com>2021-05-03 17:30:41 +0200
commitd21380728f7d16f1a5b7362b2e2b5c46ff8a8070 (patch)
tree190e3a83254cf1d4c36ec03d4ce688cf657d27c8 /core
parent7bc03523d075ae4a5a508f9bdf59a1686f7bcdce (diff)
fix(core): error registration could pollute constructors (#10422)
Co-authored-by: Luca Casonato <lucacasonato@yahoo.com>
Diffstat (limited to 'core')
-rw-r--r--core/core.js31
-rw-r--r--core/error_builder_test.js30
-rw-r--r--core/runtime.rs35
3 files changed, 83 insertions, 13 deletions
diff --git a/core/core.js b/core/core.js
index 729ca4faa..f0933d034 100644
--- a/core/core.js
+++ b/core/core.js
@@ -6,15 +6,15 @@
const { opcall } = window.Deno.core;
let opsCache = {};
- const errorMap = {
- // Builtin v8 / JS errors
- Error,
- RangeError,
- ReferenceError,
- SyntaxError,
- TypeError,
- URIError,
- };
+ const errorMap = {};
+ // Builtin v8 / JS errors
+ registerErrorClass("Error", Error);
+ registerErrorClass("RangeError", RangeError);
+ registerErrorClass("ReferenceError", ReferenceError);
+ registerErrorClass("SyntaxError", SyntaxError);
+ registerErrorClass("TypeError", TypeError);
+ registerErrorClass("URIError", URIError);
+
let nextPromiseId = 1;
const promiseMap = new Map();
const RING_SIZE = 4 * 1024;
@@ -83,23 +83,27 @@
}
function registerErrorClass(className, errorClass) {
+ registerErrorBuilder(className, (msg) => new errorClass(msg));
+ }
+
+ function registerErrorBuilder(className, errorBuilder) {
if (typeof errorMap[className] !== "undefined") {
throw new TypeError(`Error class for "${className}" already registered`);
}
- errorMap[className] = errorClass;
+ errorMap[className] = errorBuilder;
}
function unwrapOpResult(res) {
// .$err_class_name is a special key that should only exist on errors
if (res?.$err_class_name) {
const className = res.$err_class_name;
- const ErrorClass = errorMap[className];
- if (!ErrorClass) {
+ const errorBuilder = errorMap[className];
+ if (!errorBuilder) {
throw new Error(
`Unregistered error class: "${className}"\n ${res.message}\n Classes of errors returned from ops should be registered via Deno.core.registerErrorClass().`,
);
}
- throw new ErrorClass(res.message);
+ throw errorBuilder(res.message);
}
return res;
}
@@ -138,6 +142,7 @@
close,
print,
resources,
+ registerErrorBuilder,
registerErrorClass,
handleAsyncMsgFromRust,
syncOpsCache,
diff --git a/core/error_builder_test.js b/core/error_builder_test.js
new file mode 100644
index 000000000..aae47c6cd
--- /dev/null
+++ b/core/error_builder_test.js
@@ -0,0 +1,30 @@
+const { core } = Deno;
+
+class DOMException {
+ constructor(message, code) {
+ this.msg = message;
+ this.code = code;
+ }
+}
+
+core.registerErrorBuilder(
+ "DOMExceptionOperationError",
+ function DOMExceptionOperationError(msg) {
+ return new DOMException(msg, "OperationError");
+ },
+);
+
+try {
+ core.opSync("op_err", undefined, null);
+ throw new Error("op_err didn't throw!");
+} catch (err) {
+ if (!(err instanceof DOMException)) {
+ throw new Error("err not DOMException");
+ }
+ if (err.msg !== "abc") {
+ throw new Error("err.message is incorrect");
+ }
+ if (err.code !== "OperationError") {
+ throw new Error("err.code is incorrect");
+ }
+}
diff --git a/core/runtime.rs b/core/runtime.rs
index 547f6aa23..af1280373 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -1521,7 +1521,9 @@ impl JsRuntime {
#[cfg(test)]
pub mod tests {
use super::*;
+ use crate::error::custom_error;
use crate::modules::ModuleSourceFuture;
+ use crate::op_sync;
use futures::future::lazy;
use futures::FutureExt;
use std::io;
@@ -1769,6 +1771,39 @@ pub mod tests {
}
#[test]
+ fn test_error_builder() {
+ fn op_err(
+ _: &mut OpState,
+ _: (),
+ _: Option<ZeroCopyBuf>,
+ ) -> Result<(), AnyError> {
+ Err(custom_error("DOMExceptionOperationError", "abc"))
+ }
+
+ pub fn get_error_class_name(_: &AnyError) -> &'static str {
+ "DOMExceptionOperationError"
+ }
+
+ run_in_task(|mut cx| {
+ let mut runtime = JsRuntime::new(RuntimeOptions {
+ get_error_class_fn: Some(&get_error_class_name),
+ ..Default::default()
+ });
+ runtime.register_op("op_err", op_sync(op_err));
+ runtime.sync_ops_cache();
+ runtime
+ .execute(
+ "error_builder_test.js",
+ include_str!("error_builder_test.js"),
+ )
+ .unwrap();
+ if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx) {
+ unreachable!();
+ }
+ });
+ }
+
+ #[test]
fn will_snapshot() {
let snapshot = {
let mut runtime = JsRuntime::new(RuntimeOptions {