Skip to content

Commit

Permalink
add exception and receiver helper functions and use them
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Dec 28, 2024
1 parent bc4062f commit ca4668c
Show file tree
Hide file tree
Showing 18 changed files with 123 additions and 214 deletions.
8 changes: 3 additions & 5 deletions crates/dash_node_impl/src/assert.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use dash_vm::localscope::LocalScope;
use dash_vm::throw;
use dash_vm::value::function::native::{register_native_fn, CallContext};
use dash_vm::value::function::native::{CallContext, register_native_fn};
use dash_vm::value::ops::conversions::ValueConversion;
use dash_vm::value::Value;
use dash_vm::value::{ExceptionContext, Value};

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

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

// TODO: throw AssertionError
Expand Down
22 changes: 11 additions & 11 deletions crates/dash_node_impl/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use dash_proc_macro::Trace;
use dash_rt::state::State;
use dash_rt::typemap::Key;
use dash_vm::gc::ObjectId;
use dash_vm::js_std::receiver_t;
use dash_vm::localscope::LocalScope;
use dash_vm::value::arraybuffer::ArrayBuffer;
use dash_vm::value::function::native::{CallContext, register_native_fn};
Expand All @@ -13,7 +14,7 @@ use dash_vm::value::object::{NamedObject, Object, PropertyValue};
use dash_vm::value::ops::conversions::ValueConversion;
use dash_vm::value::primitive::Number;
use dash_vm::value::typedarray::{TypedArray, TypedArrayKind};
use dash_vm::value::{Root, Unpack, Value, ValueKind};
use dash_vm::value::{ExceptionContext, Root, Unpack, Value, ValueKind};
use dash_vm::{delegate, extract, throw};

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

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

let Some(source) = cx.args.first() else {
throw!(cx.scope, Error, "Missing source to `Buffer.from`")
};
let source = cx
.args
.first()
.or_type_err(cx.scope, "Missing source to `Buffer.from`")?;

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

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

let fill = cx.args.get(1).copied();
Expand Down
8 changes: 3 additions & 5 deletions crates/dash_node_impl/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::path::{self, Path, PathBuf};
use dash_middle::interner::sym;
use dash_vm::localscope::LocalScope;
use dash_vm::throw;
use dash_vm::value::function::native::{register_native_fn, CallContext};
use dash_vm::value::function::native::{CallContext, register_native_fn};
use dash_vm::value::object::{NamedObject, Object, PropertyValue};
use dash_vm::value::ops::conversions::ValueConversion;
use dash_vm::value::{Unpack, Value, ValueKind};
use dash_vm::value::{ExceptionContext, Unpack, Value, ValueKind};

use crate::state::state_mut;

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

fn parse_path(cx: CallContext) -> Result<Value, Value> {
let Some(path) = cx.args.first() else {
throw!(cx.scope, Error, "missing path to parse");
};
let path = cx.args.first().or_type_err(cx.scope, "Missing path to path")?;
let path = path.to_js_string(cx.scope)?;
let path = Path::new(path.res(cx.scope));
let dir = if path.is_dir() {
Expand Down
20 changes: 7 additions & 13 deletions crates/dash_rt_fetch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use dash_rt::event::EventMessage;
use dash_rt::module::ModuleLoader;
use dash_rt::state::State;
use dash_vm::gc::trace::{Trace, TraceCtxt};
use dash_vm::js_std::receiver_t;
use dash_vm::localscope::LocalScope;
use dash_vm::value::error::Error;
use dash_vm::value::function::native::CallContext;
use dash_vm::value::function::{Function, FunctionKind};
use dash_vm::value::object::{NamedObject, Object, PropertyValue};
use dash_vm::value::promise::Promise;
use dash_vm::value::string::JsString;
use dash_vm::value::{Unpack, Value, ValueKind};
use dash_vm::value::{ExceptionContext, Unpack, Value, ValueKind};
use dash_vm::{PromiseAction, Vm, delegate, extract, throw};
use once_cell::sync::Lazy;
use reqwest::{Client, Method};
Expand Down Expand Up @@ -100,14 +101,7 @@ fn fetch(cx: CallContext) -> Result<Value, Value> {
}

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

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

let response = match this.response.try_take() {
Some(response) => response,
None => throw!(cx.scope, Error, "HTTP Response already consumed"),
};
let response = this
.response
.try_take()
.or_err(cx.scope, "HTTP Response already consumed")?;

let promise = cx.scope.mk_promise();

Expand Down
13 changes: 4 additions & 9 deletions crates/dash_rt_http/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ use dash_rt::state::State;
use dash_vm::frame::This;
use dash_vm::gc::persistent::Persistent;
use dash_vm::gc::trace::{Trace, TraceCtxt};
use dash_vm::js_std::receiver_t;
use dash_vm::localscope::LocalScope;
use dash_vm::value::function::native::CallContext;
use dash_vm::value::function::{Function, FunctionKind};
use dash_vm::value::object::{NamedObject, Object, PropertyValue};
use dash_vm::value::ops::conversions::ValueConversion;
use dash_vm::value::root_ext::RootErrExt;
use dash_vm::value::string::JsString;
use dash_vm::value::{Unpack, Value, ValueContext, ValueKind};
use dash_vm::value::{ExceptionContext, Unpack, Value, ValueContext, ValueKind};
use dash_vm::{delegate, extract, throw};
use hyper::Body;
use tokio::sync::oneshot;
Expand Down Expand Up @@ -168,15 +169,9 @@ impl Object for HttpContext {
}

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

let sender = match this.sender.try_take() {
Some(sender) => sender,
None => throw!(cx.scope, Error, "Cannot respond twice"),
};
let sender = this.sender.try_take().or_err(cx.scope, "Cannot respond twice")?;

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

Expand Down
20 changes: 4 additions & 16 deletions crates/dash_rt_net/src/listener/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use dash_rt::wrap_async;
use dash_vm::frame::This;
use dash_vm::gc::ObjectId;
use dash_vm::gc::trace::{Trace, TraceCtxt};
use dash_vm::js_std::receiver_t;
use dash_vm::localscope::LocalScope;
use dash_vm::value::arraybuffer::ArrayBuffer;
use dash_vm::value::function::native::CallContext;
Expand Down Expand Up @@ -195,14 +196,7 @@ impl Object for TcpListenerHandle {
}

fn tcplistener_accept(cx: CallContext) -> Result<Value, Value> {
let this = cx.this.unpack();
let Some(handle) = this.downcast_ref::<TcpListenerHandle>(cx.scope) else {
throw!(
cx.scope,
TypeError,
"TcpListener.accept called on non-TcpListener object"
)
};
let handle = receiver_t::<TcpListenerHandle>(cx.scope, &cx.this, "TcpListener.prototype.accept")?;
let promise = cx.scope.mk_promise();

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

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

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

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

Expand Down
11 changes: 4 additions & 7 deletions crates/dash_vm/src/js_std/array_iterator.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use crate::throw;
use crate::value::array::ArrayIterator;
use crate::value::function::native::CallContext;
use crate::value::object::{NamedObject, Object, PropertyValue};
use crate::value::{Root, Unpack, Value, ValueContext};
use crate::value::{Root, Value, ValueContext};
use dash_middle::interner::sym;

use super::receiver_t;

pub fn next(cx: CallContext) -> Result<Value, Value> {
let this = cx.this.unpack();
let iterator = match this.downcast_ref::<ArrayIterator>(cx.scope) {
Some(it) => it,
None => throw!(cx.scope, TypeError, "Incompatible receiver"),
};
let iterator = receiver_t::<ArrayIterator>(cx.scope, &cx.this, "ArrayIterator.prototype.next")?;

let next = iterator.next(cx.scope).root(cx.scope)?;
let done = next.is_none();
Expand Down
13 changes: 4 additions & 9 deletions crates/dash_vm/src/js_std/arraybuffer.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::throw;
use crate::value::Value;
use crate::value::arraybuffer::ArrayBuffer;
use crate::value::function::native::CallContext;
use crate::value::object::NamedObject;
use crate::value::ops::conversions::ValueConversion;
use crate::value::{Unpack, Value};

use super::receiver_t;

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

pub fn byte_length(cx: CallContext) -> Result<Value, Value> {
let this = cx.this.unpack();
let Some(this) = this.downcast_ref::<ArrayBuffer>(cx.scope) else {
throw!(
cx.scope,
TypeError,
"ArrayBuffer.prototype.byteLength called on non-ArrayBuffer"
)
};
let this = receiver_t::<ArrayBuffer>(cx.scope, &cx.this, "ArrayBuffer.prototype.byteLength")?;
Ok(Value::number(this.len() as f64))
}
15 changes: 5 additions & 10 deletions crates/dash_vm/src/js_std/date.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::throw;
use crate::value::Value;
use crate::value::date::Date;
use crate::value::function::native::CallContext;
use crate::value::object::NamedObject;
use crate::value::root_ext::RootErrExt;
use crate::value::{Unpack, Value};

use super::receiver_t;

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

pub fn get_time(cx: CallContext) -> Result<Value, Value> {
let Some(this) = cx
.this
.unpack()
.downcast_ref::<Date>(cx.scope)
.map(|date| date.timestamp)
else {
throw!(cx.scope, Error, "Incompatible receiver to Date.prototype.getTime")
};
Ok(Value::number(this as f64))
let this = receiver_t::<Date>(cx.scope, &cx.this, "Date.prototype.getTime")?;
Ok(Value::number(this.timestamp as f64))
}
9 changes: 4 additions & 5 deletions crates/dash_vm/src/js_std/function.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::frame::This;
use crate::throw;
use crate::value::function::Function;
use crate::value::function::bound::BoundFunction;
use crate::value::function::native::CallContext;
use crate::value::function::Function;
use crate::value::object::Object;
use crate::value::ops::conversions::ValueConversion;
use crate::value::{Root, Typeof, Unpack, Value, ValueKind};

use super::receiver_t;

pub fn constructor(cx: CallContext) -> Result<Value, Value> {
throw!(cx.scope, Error, "Dynamic code compilation is currently not supported")
}
Expand Down Expand Up @@ -70,10 +72,7 @@ pub fn call(cx: CallContext) -> Result<Value, Value> {
}

pub fn to_string(cx: CallContext) -> Result<Value, Value> {
let this = cx.this.unpack();
let Some(this) = this.downcast_ref::<Function>(cx.scope) else {
throw!(cx.scope, TypeError, "Incompatible receiver");
};
let this = receiver_t::<Function>(cx.scope, &cx.this, "Function.prototype.toString")?;
let name = format!(
"function {}() {{ [native code] }}",
this.name().map(|s| s.res(cx.scope)).unwrap_or_default()
Expand Down
10 changes: 4 additions & 6 deletions crates/dash_vm/src/js_std/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ use crate::value::function::native::CallContext;
use crate::value::function::{Function, FunctionKind};
use crate::value::object::{NamedObject, Object, PropertyValue};
use crate::value::root_ext::RootErrExt;
use crate::value::{Root, Unpack, Value, ValueContext};
use crate::value::{Root, Value, ValueContext};
use dash_middle::interner::sym;

use super::receiver_t;

pub fn next(cx: CallContext) -> Result<Value, Value> {
let generator = cx.this.unpack();
let generator = match generator.downcast_ref::<GeneratorIterator>(cx.scope) {
Some(it) => it,
None => throw!(cx.scope, TypeError, "Incompatible receiver"),
};
let generator = receiver_t::<GeneratorIterator>(cx.scope, &cx.this, "GeneratorIterator.prototype.next")?;
let arg = cx.args.first().unwrap_or_undefined();
let frame = {
let (ip, old_stack, arguments, try_blocks) = match &mut *generator.state().borrow_mut() {
Expand Down
Loading

0 comments on commit ca4668c

Please sign in to comment.