Skip to content

Commit

Permalink
Support GetOwnProperty for string exotic object
Browse files Browse the repository at this point in the history
  • Loading branch information
jarkonik committed May 28, 2021
1 parent e577f2a commit 8e426f1
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 3 deletions.
10 changes: 10 additions & 0 deletions boa/src/builtins/string/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,3 +1093,13 @@ 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");
}
70 changes: 67 additions & 3 deletions boa/src/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::{
BoaProfiler, Context, Result,
};

use std::char::from_u32;

impl GcObject {
/// Check if object has property.
///
Expand Down Expand Up @@ -390,6 +392,70 @@ 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 char = if let Some(utf16_val) = string.encode_utf16().nth(pos) {
Value::from(from_u32(utf16_val as u32).unwrap())
} else {
return None;
};

let desc =
PropertyDescriptor::from(DataDescriptor::new(char, Attribute::ENUMERABLE));

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 let Some(_) = desc {
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 +465,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 8e426f1

Please sign in to comment.