Skip to content

Commit

Permalink
Merge e4d3dac into 4009204
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Aug 21, 2020
2 parents 4009204 + e4d3dac commit 57b5c9d
Show file tree
Hide file tree
Showing 9 changed files with 438 additions and 78 deletions.
100 changes: 100 additions & 0 deletions boa/examples/classes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use boa::{
builtins::{
object::{Class, ClassBuilder},
property::Attribute,
value::Value,
},
exec::Interpreter,
forward_val,
realm::Realm,
Result,
};

use gc::{Finalize, Trace};

#[derive(Debug, Trace, Finalize)]
struct Person {
name: String,
age: u32,
}

impl Person {
fn say_hello(this: &Value, _: &[Value], ctx: &mut Interpreter) -> 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());
}
}
ctx.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], ctx: &mut Interpreter) -> Result<Self> {
let name = args.get(0).cloned().unwrap_or_default().to_string(ctx)?;
let age = args.get(1).cloned().unwrap_or_default().to_u32(ctx)?;

let person = Person {
name: name.to_string(),
age,
};

Ok(person)
}

fn methods(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 realm = Realm::create();
let mut context = Interpreter::new(realm);

context.register_global_class::<Person>().unwrap();

forward_val(
&mut context,
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();
}
2 changes: 1 addition & 1 deletion boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ bitflags! {
}

impl FunctionFlags {
fn from_parameters(callable: bool, constructable: bool) -> Self {
pub(crate) fn from_parameters(callable: bool, constructable: bool) -> Self {
let mut flags = Self::default();

if callable {
Expand Down
15 changes: 8 additions & 7 deletions boa/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,19 @@ impl Json {
holder: &mut Value,
key: &PropertyKey,
) -> Result<Value> {
let mut value = holder.get_field(key.clone());
let value = holder.get_field(key.clone());

let obj = value.as_object().as_deref().cloned();
if let Some(obj) = obj {
for key in obj.keys() {
let v = Self::walk(reviver, ctx, &mut value, &key);
if let Value::Object(ref object) = value {
let keys: Vec<_> = object.borrow().keys().collect();

for key in keys {
let v = Self::walk(reviver, ctx, &mut value.clone(), &key);
match v {
Ok(v) if !v.is_undefined() => {
value.set_field(key.clone(), v);
value.set_field(key, v);
}
Ok(_) => {
value.remove_property(key.clone());
value.remove_property(key);
}
Err(_v) => {}
}
Expand Down
78 changes: 39 additions & 39 deletions boa/src/builtins/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,45 +282,45 @@ impl Object {
})
}

/// `Object.setPropertyOf(obj, prototype)`
///
/// This method sets the prototype (i.e., the internal `[[Prototype]]` property)
/// of a specified object to another object or `null`.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
pub fn set_prototype_of(&mut self, val: Value) -> bool {
debug_assert!(val.is_object() || val.is_null());
let current = self.prototype.clone();
if same_value(&current, &val) {
return true;
}
if !self.is_extensible() {
return false;
}
let mut p = val.clone();
let mut done = false;
while !done {
if p.is_null() {
done = true
} else if same_value(&Value::from(self.clone()), &p) {
return false;
} else {
let prototype = p
.as_object()
.expect("prototype should be null or object")
.prototype
.clone();
p = prototype;
}
}
self.prototype = val;
true
}
// /// `Object.setPropertyOf(obj, prototype)`
// ///
// /// This method sets the prototype (i.e., the internal `[[Prototype]]` property)
// /// of a specified object to another object or `null`.
// ///
// /// More information:
// /// - [ECMAScript reference][spec]
// /// - [MDN documentation][mdn]
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
// pub fn set_prototype_of(&mut self, val: Value) -> bool {
// debug_assert!(val.is_object() || val.is_null());
// let current = self.prototype.clone();
// if same_value(&current, &val) {
// return true;
// }
// if !self.is_extensible() {
// return false;
// }
// let mut p = val.clone();
// let mut done = false;
// while !done {
// if p.is_null() {
// done = true
// } else if same_value(&Value::from(self.clone()), &p) {
// return false;
// } else {
// let prototype = p
// .as_object()
// .expect("prototype should be null or object")
// .prototype
// .clone();
// p = prototype;
// }
// }
// self.prototype = val;
// true
// }

/// Returns either the prototype or null
///
Expand Down

0 comments on commit 57b5c9d

Please sign in to comment.