Module boa_engine::class
source · Expand description
Traits and structs for implementing native classes.
Native classes are implemented through the Class
trait.
§Examples
// Can also be a struct containing `Trace` types.
#[derive(Debug, Trace, Finalize, JsData)]
enum Animal {
Cat,
Dog,
Other,
}
impl Class for Animal {
// we set the binging name of this function to be `"Animal"`.
const NAME: &'static str = "Animal";
// We set the length to `2` since we accept 2 arguments in the constructor.
const LENGTH: usize = 2;
// This is what is called when we do `new Animal()` to construct the inner data of the class.
// `_new_target` is the target of the `new` invocation, in this case the `Animal` constructor
// object.
fn data_constructor(_new_target: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<Self> {
// This is equivalent to `String(arg)`.
let kind = args.get_or_undefined(0).to_string(context)?;
let animal = match kind.to_std_string_escaped().as_str() {
"cat" => Self::Cat,
"dog" => Self::Dog,
_ => Self::Other,
};
Ok(animal)
}
// This is also called on instance construction, but it receives the object wrapping the
// native data as its `instance` argument.
fn object_constructor(
instance: &JsObject,
args: &[JsValue],
context: &mut Context,
) -> JsResult<()> {
let age = args.get_or_undefined(1).to_number(context)?;
// Roughly equivalent to `this.age = Number(age)`.
instance.set(js_string!("age"), age, true, context)?;
Ok(())
}
/// This is where the class object is initialized.
fn init(class: &mut ClassBuilder) -> JsResult<()> {
class.method(
js_string!("speak"),
0,
NativeFunction::from_fn_ptr(|this, _args, _ctx| {
if let Some(object) = this.as_object() {
if let Some(animal) = object.downcast_ref::<Animal>() {
return Ok(match &*animal {
Self::Cat => js_string!("meow"),
Self::Dog => js_string!("woof"),
Self::Other => js_string!(r"¯\_(ツ)_/¯"),
}.into());
}
}
Err(JsNativeError::typ().with_message("invalid this for class method").into())
}),
);
Ok(())
}
}
fn main() {
let mut context = Context::default();
context.register_global_class::<Animal>().unwrap();
let result = context.eval(Source::from_bytes(r#"
let pet = new Animal("dog", 3);
`My pet is ${pet.age} years old. Right, buddy? - ${pet.speak()}!`
"#)).unwrap();
assert_eq!(
result.as_string().unwrap(),
&js_string!("My pet is 3 years old. Right, buddy? - woof!")
);
}
Structs§
- Class builder which allows adding methods and static methods to the class.
Traits§
- Native class.