Skip to content

Commit ca4668c

Browse files
committed
add exception and receiver helper functions and use them
1 parent bc4062f commit ca4668c

File tree

18 files changed

+123
-214
lines changed

18 files changed

+123
-214
lines changed

crates/dash_node_impl/src/assert.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use dash_vm::localscope::LocalScope;
22
use dash_vm::throw;
3-
use dash_vm::value::function::native::{register_native_fn, CallContext};
3+
use dash_vm::value::function::native::{CallContext, register_native_fn};
44
use dash_vm::value::ops::conversions::ValueConversion;
5-
use dash_vm::value::Value;
5+
use dash_vm::value::{ExceptionContext, Value};
66

77
use crate::state::state_mut;
88
use crate::symbols::NodeSymbols;
@@ -14,9 +14,7 @@ pub fn init_module(sc: &mut LocalScope<'_>) -> Result<Value, Value> {
1414
}
1515

1616
fn js_assert(cx: CallContext) -> Result<Value, Value> {
17-
let Some(value) = cx.args.first() else {
18-
throw!(cx.scope, Error, "Missing valuel to assert")
19-
};
17+
let value = cx.args.first().or_type_err(cx.scope, "Missing value to assert")?;
2018
let message = cx.args.get(1);
2119

2220
// TODO: throw AssertionError

crates/dash_node_impl/src/buffer.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use dash_proc_macro::Trace;
55
use dash_rt::state::State;
66
use dash_rt::typemap::Key;
77
use dash_vm::gc::ObjectId;
8+
use dash_vm::js_std::receiver_t;
89
use dash_vm::localscope::LocalScope;
910
use dash_vm::value::arraybuffer::ArrayBuffer;
1011
use dash_vm::value::function::native::{CallContext, register_native_fn};
@@ -13,7 +14,7 @@ use dash_vm::value::object::{NamedObject, Object, PropertyValue};
1314
use dash_vm::value::ops::conversions::ValueConversion;
1415
use dash_vm::value::primitive::Number;
1516
use dash_vm::value::typedarray::{TypedArray, TypedArrayKind};
16-
use dash_vm::value::{Root, Unpack, Value, ValueKind};
17+
use dash_vm::value::{ExceptionContext, Root, Unpack, Value, ValueKind};
1718
use dash_vm::{delegate, extract, throw};
1819

1920
use crate::state::state_mut;
@@ -80,10 +81,7 @@ fn write_byte(cx: CallContext, endianness: Endianness, size: usize) -> Result<Va
8081
None => 0,
8182
};
8283

83-
let this = cx.this.unpack();
84-
let Some(buf) = this.downcast_ref::<Buffer>(cx.scope) else {
85-
throw!(cx.scope, TypeError, "Incompatible Buffer.write* receiver")
86-
};
84+
let buf = receiver_t::<Buffer>(cx.scope, &cx.this, "Buffer.prototype.write*")?;
8785
let buf = if let Some(buf) = buf.inner.arraybuffer(cx.scope).storage().get(offset..) {
8886
buf
8987
} else {
@@ -142,9 +140,10 @@ fn from(cx: CallContext) -> Result<Value, Value> {
142140
buffer_ctor,
143141
} = State::from_vm(cx.scope).store[BufferKey];
144142

145-
let Some(source) = cx.args.first() else {
146-
throw!(cx.scope, Error, "Missing source to `Buffer.from`")
147-
};
143+
let source = cx
144+
.args
145+
.first()
146+
.or_type_err(cx.scope, "Missing source to `Buffer.from`")?;
148147

149148
let length = source.length_of_array_like(cx.scope)?;
150149
let mut buf = Vec::with_capacity(length);
@@ -170,9 +169,10 @@ fn from(cx: CallContext) -> Result<Value, Value> {
170169
}
171170

172171
fn alloc(cx: CallContext) -> Result<Value, Value> {
173-
let Some(size) = cx.args.first() else {
174-
throw!(cx.scope, Error, "Missing size argument to `Buffer.alloc`")
175-
};
172+
let size = cx
173+
.args
174+
.first()
175+
.or_type_err(cx.scope, "Missing size argument to `Buffer.alloc`")?;
176176
let size = size.to_number(cx.scope)? as usize;
177177

178178
let fill = cx.args.get(1).copied();

crates/dash_node_impl/src/path.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use std::path::{self, Path, PathBuf};
33
use dash_middle::interner::sym;
44
use dash_vm::localscope::LocalScope;
55
use dash_vm::throw;
6-
use dash_vm::value::function::native::{register_native_fn, CallContext};
6+
use dash_vm::value::function::native::{CallContext, register_native_fn};
77
use dash_vm::value::object::{NamedObject, Object, PropertyValue};
88
use dash_vm::value::ops::conversions::ValueConversion;
9-
use dash_vm::value::{Unpack, Value, ValueKind};
9+
use dash_vm::value::{ExceptionContext, Unpack, Value, ValueKind};
1010

1111
use crate::state::state_mut;
1212

@@ -22,9 +22,7 @@ pub fn init_module(sc: &mut LocalScope<'_>) -> Result<Value, Value> {
2222
}
2323

2424
fn parse_path(cx: CallContext) -> Result<Value, Value> {
25-
let Some(path) = cx.args.first() else {
26-
throw!(cx.scope, Error, "missing path to parse");
27-
};
25+
let path = cx.args.first().or_type_err(cx.scope, "Missing path to path")?;
2826
let path = path.to_js_string(cx.scope)?;
2927
let path = Path::new(path.res(cx.scope));
3028
let dir = if path.is_dir() {

crates/dash_rt_fetch/src/lib.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use dash_rt::event::EventMessage;
44
use dash_rt::module::ModuleLoader;
55
use dash_rt::state::State;
66
use dash_vm::gc::trace::{Trace, TraceCtxt};
7+
use dash_vm::js_std::receiver_t;
78
use dash_vm::localscope::LocalScope;
89
use dash_vm::value::error::Error;
910
use dash_vm::value::function::native::CallContext;
1011
use dash_vm::value::function::{Function, FunctionKind};
1112
use dash_vm::value::object::{NamedObject, Object, PropertyValue};
1213
use dash_vm::value::promise::Promise;
1314
use dash_vm::value::string::JsString;
14-
use dash_vm::value::{Unpack, Value, ValueKind};
15+
use dash_vm::value::{ExceptionContext, Unpack, Value, ValueKind};
1516
use dash_vm::{PromiseAction, Vm, delegate, extract, throw};
1617
use once_cell::sync::Lazy;
1718
use reqwest::{Client, Method};
@@ -100,14 +101,7 @@ fn fetch(cx: CallContext) -> Result<Value, Value> {
100101
}
101102

102103
fn http_response_text(cx: CallContext) -> Result<Value, Value> {
103-
let this = match cx.this.unpack() {
104-
ValueKind::Object(obj) => obj,
105-
_ => throw!(cx.scope, TypeError, "Expected a this value"),
106-
};
107-
let this = match this.extract::<HttpResponse>(cx.scope) {
108-
Some(resp) => resp,
109-
None => throw!(cx.scope, TypeError, "Invalid receiver, expected HttpResponse"),
110-
};
104+
let this = receiver_t::<HttpResponse>(cx.scope, &cx.this, "Response.prototype.text")?;
111105

112106
let (rt, event_tx) = {
113107
let state = State::from_vm_mut(cx.scope);
@@ -116,10 +110,10 @@ fn http_response_text(cx: CallContext) -> Result<Value, Value> {
116110
(rt, etx)
117111
};
118112

119-
let response = match this.response.try_take() {
120-
Some(response) => response,
121-
None => throw!(cx.scope, Error, "HTTP Response already consumed"),
122-
};
113+
let response = this
114+
.response
115+
.try_take()
116+
.or_err(cx.scope, "HTTP Response already consumed")?;
123117

124118
let promise = cx.scope.mk_promise();
125119

crates/dash_rt_http/src/lib.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ use dash_rt::state::State;
1010
use dash_vm::frame::This;
1111
use dash_vm::gc::persistent::Persistent;
1212
use dash_vm::gc::trace::{Trace, TraceCtxt};
13+
use dash_vm::js_std::receiver_t;
1314
use dash_vm::localscope::LocalScope;
1415
use dash_vm::value::function::native::CallContext;
1516
use dash_vm::value::function::{Function, FunctionKind};
1617
use dash_vm::value::object::{NamedObject, Object, PropertyValue};
1718
use dash_vm::value::ops::conversions::ValueConversion;
1819
use dash_vm::value::root_ext::RootErrExt;
1920
use dash_vm::value::string::JsString;
20-
use dash_vm::value::{Unpack, Value, ValueContext, ValueKind};
21+
use dash_vm::value::{ExceptionContext, Unpack, Value, ValueContext, ValueKind};
2122
use dash_vm::{delegate, extract, throw};
2223
use hyper::Body;
2324
use tokio::sync::oneshot;
@@ -168,15 +169,9 @@ impl Object for HttpContext {
168169
}
169170

170171
fn ctx_respond(cx: CallContext) -> Result<Value, Value> {
171-
let this = cx.this.unpack();
172-
let Some(this) = this.downcast_ref::<HttpContext>(cx.scope) else {
173-
throw!(cx.scope, TypeError, "Missing this");
174-
};
172+
let this = receiver_t::<HttpContext>(cx.scope, &cx.this, "HttpContext.prototype.respond")?;
175173

176-
let sender = match this.sender.try_take() {
177-
Some(sender) => sender,
178-
None => throw!(cx.scope, Error, "Cannot respond twice"),
179-
};
174+
let sender = this.sender.try_take().or_err(cx.scope, "Cannot respond twice")?;
180175

181176
let message = cx.args.first().unwrap_or_undefined().to_js_string(cx.scope)?;
182177

crates/dash_rt_net/src/listener/mod.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use dash_rt::wrap_async;
77
use dash_vm::frame::This;
88
use dash_vm::gc::ObjectId;
99
use dash_vm::gc::trace::{Trace, TraceCtxt};
10+
use dash_vm::js_std::receiver_t;
1011
use dash_vm::localscope::LocalScope;
1112
use dash_vm::value::arraybuffer::ArrayBuffer;
1213
use dash_vm::value::function::native::CallContext;
@@ -195,14 +196,7 @@ impl Object for TcpListenerHandle {
195196
}
196197

197198
fn tcplistener_accept(cx: CallContext) -> Result<Value, Value> {
198-
let this = cx.this.unpack();
199-
let Some(handle) = this.downcast_ref::<TcpListenerHandle>(cx.scope) else {
200-
throw!(
201-
cx.scope,
202-
TypeError,
203-
"TcpListener.accept called on non-TcpListener object"
204-
)
205-
};
199+
let handle = receiver_t::<TcpListenerHandle>(cx.scope, &cx.this, "TcpListener.prototype.accept")?;
206200
let promise = cx.scope.mk_promise();
207201

208202
let promise_id = State::from_vm_mut(cx.scope).add_pending_promise(promise);
@@ -280,10 +274,7 @@ impl Object for TcpStreamHandle {
280274
}
281275

282276
fn tcpstream_write(cx: CallContext) -> Result<Value, Value> {
283-
let this = cx.this.unpack();
284-
let Some(handle) = this.downcast_ref::<TcpStreamHandle>(cx.scope) else {
285-
throw!(cx.scope, TypeError, "TcpStream.write called on non-TcpStream object")
286-
};
277+
let handle = receiver_t::<TcpStreamHandle>(cx.scope, &cx.this, "TcpStream.prototyep.write")?;
287278
let Some(arg) = cx.args.first().map(|v| v.unpack()) else {
288279
throw!(cx.scope, ReferenceError, "TcpStream.write called without an argument")
289280
};
@@ -310,10 +301,7 @@ fn tcpstream_write(cx: CallContext) -> Result<Value, Value> {
310301
}
311302

312303
fn tcpstream_read(cx: CallContext) -> Result<Value, Value> {
313-
let this = cx.this.unpack();
314-
let Some(handle) = this.downcast_ref::<TcpStreamHandle>(cx.scope) else {
315-
throw!(cx.scope, TypeError, "TcpStream.write called on non-TcpStream object")
316-
};
304+
let handle = receiver_t::<TcpStreamHandle>(cx.scope, &cx.this, "TcpStream.prototype.write")?;
317305

318306
let (tx, rx) = oneshot::channel();
319307

crates/dash_vm/src/js_std/array_iterator.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
use crate::throw;
21
use crate::value::array::ArrayIterator;
32
use crate::value::function::native::CallContext;
43
use crate::value::object::{NamedObject, Object, PropertyValue};
5-
use crate::value::{Root, Unpack, Value, ValueContext};
4+
use crate::value::{Root, Value, ValueContext};
65
use dash_middle::interner::sym;
76

7+
use super::receiver_t;
8+
89
pub fn next(cx: CallContext) -> Result<Value, Value> {
9-
let this = cx.this.unpack();
10-
let iterator = match this.downcast_ref::<ArrayIterator>(cx.scope) {
11-
Some(it) => it,
12-
None => throw!(cx.scope, TypeError, "Incompatible receiver"),
13-
};
10+
let iterator = receiver_t::<ArrayIterator>(cx.scope, &cx.this, "ArrayIterator.prototype.next")?;
1411

1512
let next = iterator.next(cx.scope).root(cx.scope)?;
1613
let done = next.is_none();
+4-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use crate::throw;
2+
use crate::value::Value;
23
use crate::value::arraybuffer::ArrayBuffer;
34
use crate::value::function::native::CallContext;
45
use crate::value::object::NamedObject;
56
use crate::value::ops::conversions::ValueConversion;
6-
use crate::value::{Unpack, Value};
7+
8+
use super::receiver_t;
79

810
pub fn constructor(cx: CallContext) -> Result<Value, Value> {
911
let length = match cx.args.first() {
@@ -19,13 +21,6 @@ pub fn constructor(cx: CallContext) -> Result<Value, Value> {
1921
}
2022

2123
pub fn byte_length(cx: CallContext) -> Result<Value, Value> {
22-
let this = cx.this.unpack();
23-
let Some(this) = this.downcast_ref::<ArrayBuffer>(cx.scope) else {
24-
throw!(
25-
cx.scope,
26-
TypeError,
27-
"ArrayBuffer.prototype.byteLength called on non-ArrayBuffer"
28-
)
29-
};
24+
let this = receiver_t::<ArrayBuffer>(cx.scope, &cx.this, "ArrayBuffer.prototype.byteLength")?;
3025
Ok(Value::number(this.len() as f64))
3126
}

crates/dash_vm/src/js_std/date.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use crate::throw;
2+
use crate::value::Value;
23
use crate::value::date::Date;
34
use crate::value::function::native::CallContext;
45
use crate::value::object::NamedObject;
56
use crate::value::root_ext::RootErrExt;
6-
use crate::value::{Unpack, Value};
7+
8+
use super::receiver_t;
79

810
pub fn time_millis(cx: &mut CallContext) -> Result<u64, Value> {
911
let callback = match cx.scope.params().time_millis_callback {
@@ -27,13 +29,6 @@ pub fn now(mut cx: CallContext) -> Result<Value, Value> {
2729
}
2830

2931
pub fn get_time(cx: CallContext) -> Result<Value, Value> {
30-
let Some(this) = cx
31-
.this
32-
.unpack()
33-
.downcast_ref::<Date>(cx.scope)
34-
.map(|date| date.timestamp)
35-
else {
36-
throw!(cx.scope, Error, "Incompatible receiver to Date.prototype.getTime")
37-
};
38-
Ok(Value::number(this as f64))
32+
let this = receiver_t::<Date>(cx.scope, &cx.this, "Date.prototype.getTime")?;
33+
Ok(Value::number(this.timestamp as f64))
3934
}

crates/dash_vm/src/js_std/function.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use crate::frame::This;
22
use crate::throw;
3+
use crate::value::function::Function;
34
use crate::value::function::bound::BoundFunction;
45
use crate::value::function::native::CallContext;
5-
use crate::value::function::Function;
66
use crate::value::object::Object;
77
use crate::value::ops::conversions::ValueConversion;
88
use crate::value::{Root, Typeof, Unpack, Value, ValueKind};
99

10+
use super::receiver_t;
11+
1012
pub fn constructor(cx: CallContext) -> Result<Value, Value> {
1113
throw!(cx.scope, Error, "Dynamic code compilation is currently not supported")
1214
}
@@ -70,10 +72,7 @@ pub fn call(cx: CallContext) -> Result<Value, Value> {
7072
}
7173

7274
pub fn to_string(cx: CallContext) -> Result<Value, Value> {
73-
let this = cx.this.unpack();
74-
let Some(this) = this.downcast_ref::<Function>(cx.scope) else {
75-
throw!(cx.scope, TypeError, "Incompatible receiver");
76-
};
75+
let this = receiver_t::<Function>(cx.scope, &cx.this, "Function.prototype.toString")?;
7776
let name = format!(
7877
"function {}() {{ [native code] }}",
7978
this.name().map(|s| s.res(cx.scope)).unwrap_or_default()

crates/dash_vm/src/js_std/generator.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ use crate::value::function::native::CallContext;
99
use crate::value::function::{Function, FunctionKind};
1010
use crate::value::object::{NamedObject, Object, PropertyValue};
1111
use crate::value::root_ext::RootErrExt;
12-
use crate::value::{Root, Unpack, Value, ValueContext};
12+
use crate::value::{Root, Value, ValueContext};
1313
use dash_middle::interner::sym;
1414

15+
use super::receiver_t;
16+
1517
pub fn next(cx: CallContext) -> Result<Value, Value> {
16-
let generator = cx.this.unpack();
17-
let generator = match generator.downcast_ref::<GeneratorIterator>(cx.scope) {
18-
Some(it) => it,
19-
None => throw!(cx.scope, TypeError, "Incompatible receiver"),
20-
};
18+
let generator = receiver_t::<GeneratorIterator>(cx.scope, &cx.this, "GeneratorIterator.prototype.next")?;
2119
let arg = cx.args.first().unwrap_or_undefined();
2220
let frame = {
2321
let (ip, old_stack, arguments, try_blocks) = match &mut *generator.state().borrow_mut() {

0 commit comments

Comments
 (0)