Skip to content

Commit

Permalink
Support GetOwnProperty for string exotic object (#1291)
Browse files Browse the repository at this point in the history
* Support GetOwnProperty for string exotic object

* Fix clippy error

* change var name

* dont load from_u32 to namespace

* be explicit about attributes

* Update boa/src/object/internal_methods.rs

Co-authored-by: Iban Eguia <razican@protonmail.ch>

* fix utf16 emoji panic

* use map and ? operator

Co-authored-by: Iban Eguia <razican@protonmail.ch>
  • Loading branch information
jarkonik and Razican authored May 30, 2021
1 parent ac99899 commit 82e8a11
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 3 deletions.
11 changes: 11 additions & 0 deletions boa/src/builtins/string/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,3 +1093,14 @@ fn unicode_iter() {
assert_eq!(forward(&mut context, "next.value"), "undefined");
assert_eq!(forward(&mut context, "next.done"), "true");
}

#[test]
fn string_get_property() {
let mut context = Context::new();
assert_eq!(forward(&mut context, "'abc'[-1]"), "undefined");
assert_eq!(forward(&mut context, "'abc'[1]"), "\"b\"");
assert_eq!(forward(&mut context, "'abc'[2]"), "\"c\"");
assert_eq!(forward(&mut context, "'abc'[3]"), "undefined");
assert_eq!(forward(&mut context, "'abc'['foo']"), "undefined");
assert_eq!(forward(&mut context, "'😀'[0]"), "\"\\ud83d\"");
}
69 changes: 66 additions & 3 deletions boa/src/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,71 @@ impl GcObject {
}
}

/// Gets own property of 'Object'
///
#[inline]
pub fn get_own_property(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
let _timer = BoaProfiler::global().start_event("Object::get_own_property", "object");

let object = self.borrow();
match object.data {
ObjectData::String(_) => self.string_exotic_get_own_property(key),
_ => self.ordinary_get_own_property(key),
}
}

/// StringGetOwnProperty abstract operation
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-stringgetownproperty
#[inline]
pub fn string_get_own_property(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
let object = self.borrow();

match key {
PropertyKey::Index(index) => {
let string = object.as_string().unwrap();
let pos = *index as usize;

if pos >= string.len() {
return None;
}

let result_str = string.encode_utf16().nth(pos).map(|utf16_val| {
char::from_u32(u32::from(utf16_val))
.map_or_else(|| Value::from(format!("\\u{:x}", utf16_val)), Value::from)
})?;

let desc = PropertyDescriptor::from(DataDescriptor::new(
result_str,
Attribute::READONLY | Attribute::ENUMERABLE | Attribute::PERMANENT,
));

Some(desc)
}
_ => None,
}
}

/// Gets own property of 'String' exotic object
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-string-exotic-objects-getownproperty-p
#[inline]
pub fn string_exotic_get_own_property(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
let desc = self.ordinary_get_own_property(key);

if desc.is_some() {
desc
} else {
self.string_get_own_property(key)
}
}

/// The specification returns a Property Descriptor or Undefined.
///
/// These are 2 separate types and we can't do that here.
Expand All @@ -399,9 +464,7 @@ impl GcObject {
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p
#[inline]
pub fn get_own_property(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
let _timer = BoaProfiler::global().start_event("Object::get_own_property", "object");

pub fn ordinary_get_own_property(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
let object = self.borrow();
let property = match key {
PropertyKey::Index(index) => object.indexed_properties.get(&index),
Expand Down

0 comments on commit 82e8a11

Please sign in to comment.