Browse Source

Fix enumerable attribute on string length property (#974)

* Fix enumerable attribute on string length property

* Remove unnecessary conversion

* Fix length for string value

Co-authored-by: tofpie <tofpie@users.noreply.github.com>
pull/981/head
tofpie 4 years ago committed by GitHub
parent
commit
d46080d9ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      boa/src/builtins/string/mod.rs
  2. 14
      boa/src/builtins/string/tests.rs
  3. 6
      boa/src/value/mod.rs
  4. 31
      boa/src/value/tests.rs

9
boa/src/builtins/string/mod.rs

@ -13,6 +13,7 @@ pub mod string_iterator;
#[cfg(test)]
mod tests;
use crate::property::DataDescriptor;
use crate::{
builtins::{string::string_iterator::StringIterator, BuiltIn, RegExp},
object::{ConstructorBuilder, Object, ObjectData},
@ -140,9 +141,11 @@ impl String {
None => RcString::default(),
};
let length = string.encode_utf16().count();
this.set_field("length", Value::from(length as i32));
let length = DataDescriptor::new(
Value::from(string.encode_utf16().count()),
Attribute::NON_ENUMERABLE,
);
this.set_property("length", length);
this.set_data(ObjectData::String(string.clone()));

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

@ -39,6 +39,20 @@ fn new_string_has_length() {
assert_eq!(forward(&mut context, "a.length"), "4");
}
#[test]
fn new_string_has_length_not_enumerable() {
let mut context = Context::new();
let init = r#"
let a = new String("1234");
"#;
forward(&mut context, init);
assert_eq!(
forward(&mut context, "a.propertyIsEnumerable('length')"),
"false"
);
}
#[test]
fn new_utf8_string_has_length() {
let mut context = Context::new();

6
boa/src/value/mod.rs

@ -664,7 +664,11 @@ impl Value {
ObjectData::String(string.clone()),
));
// Make sure the correct length is set on our new string object
object.set("length".into(), string.chars().count().into());
object.insert_property(
PropertyKey::String("length".into()),
Value::from(string.encode_utf16().count()),
Attribute::NON_ENUMERABLE,
);
Ok(object)
}
Value::Symbol(ref symbol) => {

31
boa/src/value/tests.rs

@ -251,6 +251,37 @@ fn to_string() {
assert_eq!(f64_to_str(3e50), "3e+50");
}
#[test]
fn string_length_is_not_enumerable() {
let mut context = Context::new();
let object = Value::from("foo").to_object(&mut context).unwrap();
let length_desc = object
.get_own_property(&PropertyKey::from("length"))
.unwrap();
assert!(!length_desc.enumerable());
}
#[test]
fn string_length_is_in_utf16_codeunits() {
let mut context = Context::new();
// 😀 is one Unicode code point, but 2 UTF-16 code units
let object = Value::from("😀").to_object(&mut context).unwrap();
let length_desc = object
.get_own_property(&PropertyKey::from("length"))
.unwrap();
assert_eq!(
length_desc
.as_data_descriptor()
.unwrap()
.value()
.to_integer_or_infinity(&mut context)
.unwrap(),
IntegerOrInfinity::Integer(2)
);
}
#[test]
fn add_number_and_number() {
let mut context = Context::new();

Loading…
Cancel
Save