use boa::{
class::{Class, ClassBuilder},
gc::{Finalize, Trace},
property::Attribute,
Context, Result, Value,
};
#[derive(Debug, Trace, Finalize)]
struct Person {
name: String,
age: u32,
}
impl Person {
fn say_hello(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Some(object) = this.as_object() {
if let Some(person) = object.downcast_ref::<Person>() {
println!(
"Hello my name is {}, I'm {} years old",
person.name,
person.age );
return Ok(Value::undefined());
}
}
context.throw_type_error("'this' is not a Person object")
}
}
impl Class for Person {
const NAME: &'static str = "Person";
const LENGTH: usize = 2;
fn constructor(_this: &Value, args: &[Value], context: &mut Context) -> Result<Self> {
let name = args
.get(0)
.cloned()
.unwrap_or_default()
.to_string(context)?;
let age = args.get(1).cloned().unwrap_or_default().to_u32(context)?;
let person = Person {
name: name.to_string(),
age,
};
Ok(person) }
fn init(class: &mut ClassBuilder) -> Result<()> {
class.method("sayHello", 0, Self::say_hello);
class.static_method("is", 1, |_this, args, _ctx| {
if let Some(arg) = args.get(0) {
if let Some(object) = arg.as_object() {
if object.is::<Person>() {
return Ok(true.into()); }
}
}
Ok(false.into()) });
class.property("inheritedProperty", 10, Attribute::default());
class.static_property(
"staticProperty",
"Im a static property",
Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::PERMANENT,
);
Ok(())
}
}
fn main() {
let mut context = Context::new();
context.register_global_class::<Person>().unwrap();
context
.eval(
r"
let person = new Person('John', 19);
person.sayHello();
if (Person.is(person)) {
console.log('person is a Person class instance.');
}
if (!Person.is('Hello')) {
console.log('\'Hello\' string is not a Person class instance.');
}
console.log(Person.staticProperty);
console.log(person.inheritedProperty);
console.log(Person.prototype.inheritedProperty === person.inheritedProperty);
",
)
.unwrap();
}