Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: condition #6

Merged
merged 14 commits into from
Feb 20, 2023
Prev Previous commit
Next Next commit
feat: computed property name
  • Loading branch information
echosoar committed Feb 6, 2023
commit f33de261cc389654efbec621488be44d84b34245
4 changes: 2 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::io;

use crate::ast_token::{get_token_keyword, Token, get_token_literal};
use crate::ast_node::{ Expression, NumberLiteral, StringLiteral, Statement, IdentifierLiteral, ExpressionStatement, PropertyAccessExpression, BinaryExpression, ConditionalExpression, CallExpression, Keywords, Parameter, BlockStatement, ReturnStatement, Declaration, PropertyAssignment, ObjectLiteral, ElementAccessExpression, FunctionDeclaration, PostfixUnaryExpression, PrefixUnaryExpression, AssignExpression, GroupExpression, VariableDeclaration, VariableDeclarationStatement, VariableFlag, ClassDeclaration, ClassMethodDeclaration, ArrayLiteral};
use crate::ast_node::{ Expression, NumberLiteral, StringLiteral, Statement, IdentifierLiteral, ExpressionStatement, PropertyAccessExpression, BinaryExpression, ConditionalExpression, CallExpression, Keywords, Parameter, BlockStatement, ReturnStatement, Declaration, PropertyAssignment, ObjectLiteral, ElementAccessExpression, FunctionDeclaration, PostfixUnaryExpression, PrefixUnaryExpression, AssignExpression, GroupExpression, VariableDeclaration, VariableDeclarationStatement, VariableFlag, ClassDeclaration, ClassMethodDeclaration, ArrayLiteral, ComputedPropertyName};
use crate::ast_utils::{get_hex_number_value, chars_to_string};
pub struct AST {
// 当前字符
Expand Down Expand Up @@ -1359,7 +1359,7 @@ impl AST{
self.next();
let key = self.parse_expression();
self.check_token_and_next(Token::RightBracket);
key
Expression::ComputedPropertyName(ComputedPropertyName { expression: Box::new(key) })
},
_ => Expression::Unknown
}
Expand Down
8 changes: 8 additions & 0 deletions src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ pub enum Expression {
Object(ObjectLiteral),
Array(ArrayLiteral),
Function(FunctionDeclaration),
// {[a]: 12}
ComputedPropertyName(ComputedPropertyName),
// for class
Class(ClassDeclaration),
Constructor(FunctionDeclaration),
Expand Down Expand Up @@ -97,6 +99,12 @@ pub struct FunctionDeclaration {
pub declarations: Vec<Declaration>,
}

// ES2015 Computed Property Name
#[derive(Debug, Clone, PartialEq)]
pub struct ComputedPropertyName {
pub expression: Box<Expression>
}

#[derive(Debug, Clone, PartialEq)]
pub struct ClassDeclaration {
pub name: IdentifierLiteral,
Expand Down
3 changes: 2 additions & 1 deletion src/builtins/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ fn array_join(ctx: &mut CallContext, args: Vec<Value>) -> Value {
}
}
let mut string_list: Vec<String> = vec![];
let global = ctx.global.upgrade().unwrap();
let iter = |_: i32, value: &Value| {
string_list.push(value.to_string());
string_list.push(value.to_string(&global));
};
array_iter_mut(ctx, iter);
Value::String(string_list.join(join))
Expand Down
3 changes: 2 additions & 1 deletion src/builtins/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ pub fn bind_global_boolean(global: &Rc<RefCell<Object>>) {
// Boolean.prototype.toString
fn boolean_to_string(ctx: &mut CallContext, _: Vec<Value>) -> Value {
let value = boolean_value_of(ctx, vec![]);
Value::String(value.to_string())
let global = ctx.global.upgrade().unwrap();
Value::String(value.to_string(&global))
}

// Boolean.prototype.valueOf
Expand Down
9 changes: 6 additions & 3 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,14 @@ impl Context {
// println!("PropertyAccess: {:?} {:?}",left_obj, right);
ValueInfo { value, name: Some(right.clone()), reference: Some(Value::Object(left_obj)) }
},
Expression::ComputedPropertyName(property_name) => {
ValueInfo { value: self.execute_expression(&property_name.expression), name: None, reference: None }
},
Expression::ElementAccess(element_access) => {
// expression[argument]
let left = self.execute_expression(&element_access.expression);
let left_obj = left.to_object(&self.global);
let right = self.execute_expression(&element_access.argument).to_string();
let right = self.execute_expression(&element_access.argument).to_string(&self.global);
let value = (*left_obj).borrow().get_value(right.clone());
ValueInfo { value, name: Some(right.clone()), reference: Some(Value::Object(left_obj)) }
},
Expand Down Expand Up @@ -187,7 +190,7 @@ impl Context {
if expression.operator == Token::Plus {
// 如果有一个是字符串,那就返回字符串
if left.is_string() || right.is_string() {
return Value::String(left.to_string() + right.to_string().as_str())
return Value::String(left.to_string(&self.global) + right.to_string(&self.global).as_str())
}
}

Expand Down Expand Up @@ -271,7 +274,7 @@ impl Context {
// 绑定属性
for property_index in 0..expression.properties.len() {
let property = &expression.properties[property_index];
let name = self.execute_expression(&property.name).to_string();
let name = self.execute_expression(&property.name).to_string(&self.global);
let mut initializer = self.execute_expression(&property.initializer);
initializer.bind_name(name.clone());
object_mut.define_property(name, Property {
Expand Down
56 changes: 41 additions & 15 deletions src/value.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::cell::RefCell;
use std::rc::{Weak, Rc};
use crate::ast_node::{Statement, IdentifierLiteral, ClassType};
use crate::ast_node::{Statement, IdentifierLiteral, ClassType, CallContext};
use crate::builtins::boolean::create_boolean;
use crate::builtins::number::create_number;
use crate::builtins::object::{Object, Property};
use crate::builtins::string::create_string;
use crate::scope::Scope;


Expand Down Expand Up @@ -109,7 +111,15 @@ impl Clone for Value {
Value::Function(rc_value) => {
Value::Function(Rc::clone(rc_value))
},

Value::StringObj(rc_value) => {
Value::StringObj(Rc::clone(rc_value))
},
Value::NumberObj(rc_value) => {
Value::NumberObj(Rc::clone(rc_value))
},
Value::BooleanObj(rc_value) => {
Value::BooleanObj(Rc::clone(rc_value))
},
Value::String(str) => Value::String(str.clone()),
Value::Number(num) => Value::Number(*num),
Value::Boolean(bool) => Value::Boolean(*bool),
Expand All @@ -133,7 +143,7 @@ impl Value {
}
return false
}
pub fn to_string(&self) -> String {
pub fn to_string(&self, global: &Rc<RefCell<Object>>) -> String {
match self {
Value::String(str) => str.clone(),
Value::Number(number) => number.to_string(),
Expand All @@ -145,15 +155,15 @@ impl Value {
}
},
Value::NAN => String::from("NaN"),
Value::Array(_) => {
// let mut arr = array.borrow_mut();
// let mut ctx = &CallContext {
// // TODO: self
// this: Rc::downgrade(array),
// };
// arr.to_string(&mut ctx)
// TODO: arr.call("toString")
String::from("")
Value::Array(obj) => {
let weak = Rc::downgrade(obj);
let call_ctx = &mut CallContext {
global: Rc::downgrade(global),
this: weak,
reference: None,
};
let value = Object::call(call_ctx, String::from("toString"), vec![]);
return value.to_string(global)
},
_ => String::from(""),
}
Expand Down Expand Up @@ -222,14 +232,27 @@ impl Value {
pub fn to_object(&self, global: &Rc<RefCell<Object>>) -> Rc<RefCell<Object>> {
let default = Rc::new(RefCell::new(Object::new(ClassType::Object,None)));
match self {
Value::String(string) => {
let obj = create_string(global, Value::String(string.to_owned()));
if let Value::StringObj(obj) = obj {
return obj;
}
return default;
},
Value::Number(number) => {
let obj = create_number(global, Value::Number(number.to_owned()));
if let Value::NumberObj(obj) = obj {
return obj;
}
return default;
},
Value::Boolean(boolean) => {
let boolobj = create_boolean(global, Value::Boolean(boolean.to_owned()));
if let Value::BooleanObj(obj) = boolobj {
let obj = create_boolean(global, Value::Boolean(boolean.to_owned()));
if let Value::BooleanObj(obj) = obj {
return obj;
}
return default;
},
// TODO: number、string
_ => {
let rc_obj = self.to_weak_rc_object();
if let Some(wrc) = rc_obj {
Expand All @@ -250,6 +273,9 @@ impl Value {
Value::Object(obj) => Some(Rc::downgrade(obj)),
Value::Function(function) => Some(Rc::downgrade(function)),
Value::Array(array) => Some(Rc::downgrade(array)),
Value::StringObj(obj) => Some(Rc::downgrade(obj)),
Value::NumberObj(obj) => Some(Rc::downgrade(obj)),
Value::BooleanObj(obj) => Some(Rc::downgrade(obj)),
Value::RefObject(obj) => Some(obj.clone()),
_ => None
}
Expand Down
23 changes: 12 additions & 11 deletions tests/object_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use jsi::{JSI, ast_node::{Expression, Statement, ObjectLiteral, ExpressionStatement, PropertyAssignment, NumberLiteral, StringLiteral, Keywords, BinaryExpression}, ast_token::Token, value::Value};
use jsi::{JSI, ast_node::{Expression, Statement, ObjectLiteral, ExpressionStatement, PropertyAssignment, NumberLiteral, StringLiteral, Keywords, BinaryExpression, ComputedPropertyName}, ast_token::Token, value::Value};

#[test]
fn ast_base() {
Expand All @@ -21,10 +21,12 @@ fn ast_base() {
initializer: Box::new(Expression::String(StringLiteral { literal: String::from("'123'"), value: String::from("123") })),
},
PropertyAssignment{
name: Box::new(Expression::Binary(BinaryExpression {
left: Box::new(Expression::Number(NumberLiteral { literal: String::from("1"), value: 1f64 })),
operator: Token::Plus,
right: Box::new(Expression::String(StringLiteral { literal: String::from("'a'"), value: String::from("a") })),
name: Box::new(Expression::ComputedPropertyName(ComputedPropertyName {
expression: Box::new(Expression::Binary(BinaryExpression {
left: Box::new(Expression::Number(NumberLiteral { literal: String::from("1"), value: 1f64 })),
operator: Token::Plus,
right: Box::new(Expression::String(StringLiteral { literal: String::from("'a'"), value: String::from("a") })),
}))
})),
initializer: Box::new(Expression::Keyword(Keywords::False)),
}
Expand Down Expand Up @@ -104,12 +106,11 @@ fn run_object_as_param_ref() {
}

#[test]
fn run_object_keys() {
fn run_object_with_array_key() {
let mut jsi = JSI::new();
let result = jsi.run(String::from("\
let obj = { a: 123, b: false, c: 'xxx'}\n
// Object.keys returns an array\n
/* array.toString() */
Object.keys(obj).toString()"));
assert_eq!(result , Value::String(String::from("a,b,c")));
let a = [1,2]\n
let b = {[a]: 3}\n
Object.keys(b).toString()"));
assert_eq!(result , Value::String(String::from("1,2")));
}