mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 06:06:38 +00:00
JavaScript: getOwnPropertyNames lists an array's length after its other names
Section 15.2.3.4 leaves the order of the names open. An array's length now comes after its indices and other properties, so Object.getOwnPropertyNames([0, 1, 2]) gives 0,1,2,length, as later editions and test262 expect. length is not enumerable, so Object.keys and for-in are unchanged.
This commit is contained in:
@@ -100,7 +100,8 @@ fn object_functions_list_create_and_lock_objects() {
|
||||
);
|
||||
truth("Object.getPrototypeOf(Object.create(null)) === null && Object.getPrototypeOf([]) === Array.prototype");
|
||||
assert_eq!(string("Object.getOwnPropertyNames(Object('ab')).join()"), "0,1,length");
|
||||
assert_eq!(string("var a = [5]; a.k = 1; Object.getOwnPropertyNames(a).join()"), "length,0,k");
|
||||
assert_eq!(string("Object.getOwnPropertyNames([0, 1, 2]).join()"), "0,1,2,length");
|
||||
assert_eq!(string("var a = [5]; a.k = 1; Object.getOwnPropertyNames(a).join()"), "0,k,length");
|
||||
// Object.keys lists names in the order for-in visits them (section 15.2.3.14).
|
||||
assert_eq!(string("var o = {b: 1, a: 2, 3: 3}, s = ''; for (var k in o) s += k; Object.keys(o).join('') === s ? s : 'differs'"), "ba3");
|
||||
truth("var o = Object.seal({x: 1}); o.x = 2; delete o.x; o.y = 1; o.x === 2 && o.y === undefined && Object.isSealed(o) && !Object.isFrozen(o)");
|
||||
|
||||
+10
-6
@@ -1173,27 +1173,31 @@ impl Interp {
|
||||
}
|
||||
|
||||
/// The names of an object's own properties (section 15.2.3.4): a String object's indices and
|
||||
/// an array's or String object's `length` first, then the rest in the order they were added,
|
||||
/// which is the order `for-in` visits them. Each name takes a unit of fuel, and the heap for
|
||||
/// the list is checked first.
|
||||
/// `length` first, then the rest in the order they were added, which is the order `for-in`
|
||||
/// visits them, then an array's `length`. Each name takes a unit of fuel, and the heap for the
|
||||
/// list is checked first.
|
||||
pub(crate) fn own_keys(&mut self, id: ObjId) -> JsResult<Vec<Key>> {
|
||||
let o = self.object(id)?;
|
||||
let string_len = if let Class::String(s) = &o.class { s.len() } else { 0 };
|
||||
let has_length = matches!(o.class, Class::Array { .. } | Class::String(_));
|
||||
let count = o.props.len().saturating_add(string_len).saturating_add(usize::from(has_length));
|
||||
let is_string = matches!(o.class, Class::String(_));
|
||||
let is_array = matches!(o.class, Class::Array { .. });
|
||||
let count = o.props.len().saturating_add(string_len).saturating_add(usize::from(is_string || is_array));
|
||||
self.reserve_heap(index_keys_bytes(string_len).saturating_add(count.saturating_mul(KEY_ENTRY_BYTES)))?;
|
||||
let mut out = Vec::with_capacity(count);
|
||||
for i in 0..string_len {
|
||||
self.use_fuel()?;
|
||||
out.push(index_key(u32::try_from(i).unwrap_or(u32::MAX)));
|
||||
}
|
||||
if has_length {
|
||||
if is_string {
|
||||
out.push(key("length"));
|
||||
}
|
||||
for _ in 0..self.object(id)?.props.len() {
|
||||
self.use_fuel()?;
|
||||
}
|
||||
out.extend(self.object(id)?.props.keys());
|
||||
if is_array {
|
||||
out.push(key("length"));
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user