From 8e426f19af4ef07e12ebc587fb8e0c41a719c3bc Mon Sep 17 00:00:00 2001 From: Jaroslaw Konik Date: Fri, 28 May 2021 19:13:33 +0200 Subject: [PATCH] Support GetOwnProperty for string exotic object --- boa/src/builtins/string/tests.rs | 10 +++++ boa/src/object/internal_methods.rs | 70 ++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/boa/src/builtins/string/tests.rs b/boa/src/builtins/string/tests.rs index 0e5f0791600..1cbe3314beb 100644 --- a/boa/src/builtins/string/tests.rs +++ b/boa/src/builtins/string/tests.rs @@ -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"); +} diff --git a/boa/src/object/internal_methods.rs b/boa/src/object/internal_methods.rs index 80246e0a551..f4c9eba45b7 100644 --- a/boa/src/object/internal_methods.rs +++ b/boa/src/object/internal_methods.rs @@ -12,6 +12,8 @@ use crate::{ BoaProfiler, Context, Result, }; +use std::char::from_u32; + impl GcObject { /// Check if object has property. /// @@ -390,6 +392,70 @@ impl GcObject { } } + /// Gets own property of 'Object' + /// + #[inline] + pub fn get_own_property(&self, key: &PropertyKey) -> Option { + 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 { + 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 { + 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. @@ -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 { - let _timer = BoaProfiler::global().start_event("Object::get_own_property", "object"); - + pub fn ordinary_get_own_property(&self, key: &PropertyKey) -> Option { let object = self.borrow(); let property = match key { PropertyKey::Index(index) => object.indexed_properties.get(&index),