Skip to content

Commit

Permalink
add globally-scoped eval
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Jan 18, 2024
1 parent 50ffedf commit b5e9f3c
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 4 deletions.
1 change: 1 addition & 0 deletions crates/dash_middle/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub mod sym {
PI,
isFinite,
isNaN,
eval,
isSafeInteger,
Number,
toFixed,
Expand Down
2 changes: 1 addition & 1 deletion crates/dash_parser/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,12 +435,12 @@ impl<'a, 'interner> Parser<'a, 'interner> {
TokenType::LeftSquareBrace => {
let mut items = Vec::new();
while !self.expect_token_type_and_skip(&[TokenType::RightSquareBrace], false) {
self.expect_token_type_and_skip(&[TokenType::Comma], false);
if let Some(spread) = self.parse_spread_operator(false) {
items.push(ArrayMemberKind::Spread(spread));
} else {
items.push(ArrayMemberKind::Item(self.parse_yield()?));
}
self.expect_token_type_and_skip(&[TokenType::Comma], false);
}
let rbrace_span = self.previous()?.span;
Expr {
Expand Down
20 changes: 18 additions & 2 deletions crates/dash_vm/src/js_std/global.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use dash_middle::parser::error::IntoFormattableErrors;

use crate::eval::EvalError;
use crate::throw;
use crate::value::function::native::CallContext;
use crate::value::ops::conversions::ValueConversion;
use crate::value::{Value, ValueContext};
use crate::value::{Root, Value, ValueContext};

#[rustfmt::skip]
pub fn is_nan(cx: CallContext) -> Result<Value, Value> {
// 1. Let num be ? ToNumber(number).
let num = cx.args.first().unwrap_or_undefined().to_number(cx.scope)?;
Expand All @@ -11,6 +14,19 @@ pub fn is_nan(cx: CallContext) -> Result<Value, Value> {
Ok(Value::Boolean(num.is_nan()))
}

pub fn eval(cx: CallContext) -> Result<Value, Value> {
let source = match cx.args.first().unwrap_or_undefined() {
Value::String(s) => s.res(cx.scope).to_owned(),
other => return Ok(other),
};

match cx.scope.eval(&source, Default::default()) {
Ok(v) => Ok(v.root(cx.scope)),
Err(EvalError::Exception(ex)) => Err(ex.root(cx.scope)),
Err(EvalError::Middle(err)) => throw!(cx.scope, SyntaxError, "{}", err.formattable(&source, true)),
}
}

pub fn log(cx: CallContext) -> Result<Value, Value> {
for arg in cx.args {
let tstr = arg.to_js_string(cx.scope)?;
Expand Down
1 change: 1 addition & 0 deletions crates/dash_vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,7 @@ impl Vm {
object_ctor.clone(),
[
(sym::isNaN, scope.statics.is_nan.clone()),
(sym::eval, scope.statics.eval.clone()),
(sym::isFinite, scope.statics.is_finite.clone()),
(sym::parseFloat, scope.statics.parse_float.clone()),
(sym::parseInt, scope.statics.parse_int.clone()),
Expand Down
2 changes: 2 additions & 0 deletions crates/dash_vm/src/statics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct Statics {
pub function_call: Handle,
pub function_to_string: Handle,
pub is_nan: Handle,
pub eval: Handle,
pub is_finite: Handle,
pub parse_float: Handle,
pub parse_int: Handle,
Expand Down Expand Up @@ -301,6 +302,7 @@ impl Statics {
string_ctor: function(gc, sym::String, js_std::string::constructor),
string_prototype: builtin_object(gc, BoxedString::with_obj(sym::empty.into(), NamedObject::null())),
is_nan: function(gc, sym::isNaN, js_std::global::is_nan),
eval: function(gc, sym::eval, js_std::global::eval),
is_finite: function(gc, sym::isFinite, js_std::global::is_finite),
parse_float: function(gc, sym::parseFloat, js_std::global::parse_float),
parse_int: function(gc, sym::parseInt, js_std::global::parse_int),
Expand Down
3 changes: 2 additions & 1 deletion crates/dash_vm/src/value/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,10 @@ pub(crate) fn adjust_stack_from_flat_call(
// NB: Order is important, this needs to happen before pushing remaining
// missing undefined values and truncating
let rest = if user_function.inner().rest_local.is_some() {
let stack_len = scope.stack.len();
let args = scope
.stack
.drain(old_sp + expected_args..)
.drain((old_sp + expected_args).min(stack_len)..)
.map(PropertyValue::static_default)
.collect();

Expand Down

0 comments on commit b5e9f3c

Please sign in to comment.