mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
core: gracefully handle bad op id (#3131)
This commit is contained in:
parent
ec44b5b6af
commit
6257b4044a
5 changed files with 57 additions and 6 deletions
|
@ -311,12 +311,19 @@ impl Isolate {
|
|||
) {
|
||||
let isolate = unsafe { Isolate::from_raw_ptr(user_data) };
|
||||
|
||||
let op = isolate.op_registry.call(
|
||||
let maybe_op = isolate.op_registry.call(
|
||||
op_id,
|
||||
control_buf.as_ref(),
|
||||
PinnedBuf::new(zero_copy_buf),
|
||||
);
|
||||
|
||||
let op = match maybe_op {
|
||||
Some(op) => op,
|
||||
None => {
|
||||
return isolate.throw_exception(&format!("Unknown op id: {}", op_id))
|
||||
}
|
||||
};
|
||||
|
||||
// To avoid latency problems we eagerly poll 50 futures and then
|
||||
// allow to poll ops from `pending_ops`
|
||||
let op = if isolate.eager_poll_count != 50 {
|
||||
|
@ -414,6 +421,13 @@ impl Isolate {
|
|||
}
|
||||
}
|
||||
|
||||
fn throw_exception(&mut self, exception_text: &str) {
|
||||
let text = CString::new(exception_text).unwrap();
|
||||
unsafe {
|
||||
libdeno::deno_throw_exception(self.libdeno_isolate, text.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
fn respond(
|
||||
&mut self,
|
||||
maybe_buf: Option<(OpId, &[u8])>,
|
||||
|
@ -1418,6 +1432,26 @@ pub mod tests {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pre_dispatch() {
|
||||
run_in_task(|| {
|
||||
let (mut isolate, _dispatch_count) = setup(Mode::OverflowResAsync);
|
||||
js_check(isolate.execute(
|
||||
"bad_op_id.js",
|
||||
r#"
|
||||
let thrown;
|
||||
try {
|
||||
Deno.core.dispatch(100, []);
|
||||
} catch (e) {
|
||||
thrown = e;
|
||||
}
|
||||
assert(thrown == "Unknown op id: 100");
|
||||
"#,
|
||||
));
|
||||
assert_eq!(Async::Ready(()), isolate.poll().unwrap());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_js() {
|
||||
run_in_task(|| {
|
||||
|
|
|
@ -266,6 +266,7 @@ extern "C" {
|
|||
pub fn deno_check_promise_errors(i: *const isolate);
|
||||
pub fn deno_lock(i: *const isolate);
|
||||
pub fn deno_unlock(i: *const isolate);
|
||||
pub fn deno_throw_exception(i: *const isolate, text: *const c_char);
|
||||
pub fn deno_respond(
|
||||
i: *const isolate,
|
||||
user_data: *const c_void,
|
||||
|
|
|
@ -160,6 +160,12 @@ void deno_pinned_buf_delete(deno_pinned_buf* buf) {
|
|||
auto _ = deno::PinnedBuf(buf);
|
||||
}
|
||||
|
||||
void deno_throw_exception(Deno* d_, const char* text) {
|
||||
auto* d = unwrap(d_);
|
||||
auto* isolate = d->isolate_;
|
||||
isolate->ThrowException(deno::v8_str(text));
|
||||
}
|
||||
|
||||
void deno_respond(Deno* d_, void* user_data, deno_op_id op_id, deno_buf buf) {
|
||||
auto* d = unwrap(d_);
|
||||
if (d->current_args_ != nullptr) {
|
||||
|
|
|
@ -110,6 +110,8 @@ void deno_execute(Deno* d, void* user_data, const char* js_filename,
|
|||
// If a JS exception was encountered, deno_last_exception() will be non-NULL.
|
||||
void deno_respond(Deno* d, void* user_data, deno_op_id op_id, deno_buf buf);
|
||||
|
||||
void deno_throw_exception(Deno* d, const char* text);
|
||||
|
||||
// consumes zero_copy
|
||||
void deno_pinned_buf_delete(deno_pinned_buf* buf);
|
||||
|
||||
|
|
18
core/ops.rs
18
core/ops.rs
|
@ -63,21 +63,26 @@ impl OpRegistry {
|
|||
op_map_json.as_bytes().to_owned().into_boxed_slice()
|
||||
}
|
||||
|
||||
/// This function returns None only if op with given id doesn't exist in registry.
|
||||
pub fn call(
|
||||
&self,
|
||||
op_id: OpId,
|
||||
control: &[u8],
|
||||
zero_copy_buf: Option<PinnedBuf>,
|
||||
) -> CoreOp {
|
||||
) -> Option<CoreOp> {
|
||||
// Op with id 0 has special meaning - it's a special op that is always
|
||||
// provided to retrieve op id map. The map consists of name to `OpId`
|
||||
// mappings.
|
||||
if op_id == 0 {
|
||||
return Op::Sync(self.json_map());
|
||||
return Some(Op::Sync(self.json_map()));
|
||||
}
|
||||
|
||||
let d = &*self.dispatchers.get(op_id as usize).expect("Op not found!");
|
||||
d(control, zero_copy_buf)
|
||||
let d = match self.dispatchers.get(op_id as usize) {
|
||||
Some(handler) => &*handler,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
Some(d(control, zero_copy_buf))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,11 +106,14 @@ fn test_op_registry() {
|
|||
expected.insert("test".to_string(), 1);
|
||||
assert_eq!(op_registry.name_to_id, expected);
|
||||
|
||||
let res = op_registry.call(test_id, &[], None);
|
||||
let res = op_registry.call(test_id, &[], None).unwrap();
|
||||
if let Op::Sync(buf) = res {
|
||||
assert_eq!(buf.len(), 0);
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
assert_eq!(c.load(atomic::Ordering::SeqCst), 1);
|
||||
|
||||
let res = op_registry.call(100, &[], None);
|
||||
assert!(res.is_none());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue