Skip to content

Commit b6308e5

Browse files
authored
refactor: simplify async op error construction (#1039)
Removes usage of serde_v8 for constructing errors
1 parent eb0cfb1 commit b6308e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+268
-390
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/00_infra.js

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
Promise,
1818
PromiseReject,
1919
PromiseResolve,
20-
PromisePrototypeThen,
20+
PromisePrototypeCatch,
2121
RangeError,
2222
ReferenceError,
2323
SafeArrayIterator,
@@ -133,18 +133,22 @@
133133
MapPrototypeSet(promiseMap, oldPromiseId, oldPromise);
134134
}
135135

136-
const promise = new Promise((resolve) => {
137-
promiseRing[idx] = resolve;
136+
const promise = new Promise((resolve, reject) => {
137+
promiseRing[idx] = [resolve, reject];
138138
});
139-
const wrappedPromise = PromisePrototypeThen(
139+
const wrappedPromise = PromisePrototypeCatch(
140140
promise,
141-
unwrapOpError(),
141+
(res) => {
142+
// recreate the stacktrace and strip eventLoopTick() calls from stack trace
143+
ErrorCaptureStackTrace(res, eventLoopTick);
144+
throw res;
145+
},
142146
);
143147
wrappedPromise[promiseIdSymbol] = promiseId;
144148
return wrappedPromise;
145149
}
146150

147-
function __resolvePromise(promiseId, res) {
151+
function __resolvePromise(promiseId, res, isOk) {
148152
// Check if out of ring bounds, fallback to map
149153
const outOfBounds = promiseId < nextPromiseId - RING_SIZE;
150154
if (outOfBounds) {
@@ -153,7 +157,11 @@
153157
throw "Missing promise in map @ " + promiseId;
154158
}
155159
MapPrototypeDelete(promiseMap, promiseId);
156-
promise(res);
160+
if (isOk) {
161+
promise[0](res);
162+
} else {
163+
promise[1](res);
164+
}
157165
} else {
158166
// Otherwise take from ring
159167
const idx = promiseId % RING_SIZE;
@@ -162,7 +170,11 @@
162170
throw "Missing promise in ring @ " + promiseId;
163171
}
164172
promiseRing[idx] = NO_PROMISE;
165-
promise(res);
173+
if (isOk) {
174+
promise[0](res);
175+
} else {
176+
promise[1](res);
177+
}
166178
}
167179
}
168180

@@ -177,38 +189,6 @@
177189
return promiseRing[idx] != NO_PROMISE;
178190
}
179191

180-
function unwrapOpError() {
181-
return (res) => {
182-
// .$err_class_name is a special key that should only exist on errors
183-
const className = res?.$err_class_name;
184-
if (!className) {
185-
return res;
186-
}
187-
188-
const errorBuilder = errorMap[className];
189-
const err = errorBuilder ? errorBuilder(res.message) : new Error(
190-
`Unregistered error class: "${className}"\n ${res.message}\n Classes of errors returned from ops should be registered via Deno.core.registerErrorClass().`,
191-
);
192-
193-
if (res.additional_properties) {
194-
for (
195-
const property of new SafeArrayIterator(res.additional_properties)
196-
) {
197-
const key = property[0];
198-
if (!(key in err)) {
199-
ObjectDefineProperty(err, key, {
200-
value: property[1],
201-
writable: false,
202-
});
203-
}
204-
}
205-
}
206-
// Strip eventLoopTick() calls from stack trace
207-
ErrorCaptureStackTrace(err, eventLoopTick);
208-
throw err;
209-
};
210-
}
211-
212192
function setUpAsyncStub(opName, originalOp, maybeProto) {
213193
let fn;
214194

core/01_core.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,12 @@
161161
// responses of async ops.
162162
function eventLoopTick() {
163163
// First respond to all pending ops.
164-
for (let i = 0; i < arguments.length - 3; i += 2) {
164+
for (let i = 0; i < arguments.length - 3; i += 3) {
165165
const promiseId = arguments[i];
166-
const res = arguments[i + 1];
167-
__resolvePromise(promiseId, res);
166+
const isOk = arguments[i + 1];
167+
const res = arguments[i + 2];
168+
169+
__resolvePromise(promiseId, res, isOk);
168170
}
169171
// Drain nextTick queue if there's a tick scheduled.
170172
if (arguments[arguments.length - 1]) {

core/error.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright 2018-2025 the Deno authors. MIT license.
22

33
pub use super::modules::ModuleConcreteError;
4-
pub use super::runtime::op_driver::OpError;
5-
pub use super::runtime::op_driver::OpErrorWrapper;
64
pub use crate::io::ResourceError;
75
pub use crate::modules::ModuleLoaderError;
86
use crate::runtime::v8_static_strings;

core/examples/hello_world.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use deno_core::*;
77
/// An op for summing an array of numbers. The op-layer automatically
88
/// deserializes inputs and serializes the returned Result & value.
99
#[op2]
10-
fn op_sum(#[serde] nums: Vec<f64>) -> Result<f64, deno_core::error::OpError> {
10+
fn op_sum(#[serde] nums: Vec<f64>) -> Result<f64, deno_error::JsErrorBox> {
1111
// Sum inputs
1212
let sum = nums.iter().fold(0.0, |a, v| a + v);
1313
// return as a Result<f64, OpError>

core/examples/op2.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
// Copyright 2018-2025 the Deno authors. MIT license.
22

33
use anyhow::Context;
4-
use deno_core::error::OpError;
54
use deno_core::*;
65
use std::rc::Rc;
76

87
#[op2]
98
fn op_use_state(
109
state: &mut OpState,
1110
#[global] callback: v8::Global<v8::Function>,
12-
) -> Result<(), OpError> {
11+
) -> Result<(), deno_error::JsErrorBox> {
1312
state.put(callback);
1413
Ok(())
1514
}

0 commit comments

Comments
 (0)