Browse Source

Support GetOwnProperty for string exotic object (#1291)

* 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>
pull/1297/head
Jarosław Konik 4 years ago committed by GitHub
parent
commit
82e8a1197a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      boa/src/builtins/string/tests.rs
  2. 69
      boa/src/object/internal_methods.rs

11
boa/src/builtins/string/tests.rs

@ -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
boa/src/object/internal_methods.rs

@ -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.
@ -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),

Loading…
Cancel
Save