Skip to content

Commit b2d4596

Browse files
ssrliveCopilot
andcommitted
Fix class static property ordering: preserve insertion order for length/name
Add clear_attr_markers() helper that removes attribute hidden-keys without removing the main key from IndexMap. Use it in InitProperty's VmFunction handler so that IndexMap::insert updates the value in-place, preserving the original insertion order for built-in keys like 'length' and 'name' when overridden by static class methods. Fixes cluster 23: fn-length-static-precedence-order and fn-name-static-precedence-order tests now pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent fa42d86 commit b2d4596

File tree

3 files changed

+15
-5
lines changed

3 files changed

+15
-5
lines changed

src/core/property_descriptor.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,13 @@ pub fn write_attrs_to_legacy_map<'gc>(map: &mut indexmap::IndexMap<String, Value
719719
/// entries from a legacy hidden-key map.
720720
pub fn remove_property_completely<'gc>(map: &mut indexmap::IndexMap<String, Value<'gc>>, key: &str) {
721721
map.shift_remove(key);
722+
clear_attr_markers(map, key);
723+
}
724+
725+
/// Clear attribute markers and accessor hidden-keys for `key` WITHOUT removing
726+
/// the key itself. This allows `IndexMap::insert` to update the value in-place
727+
/// (preserving insertion order) rather than appending at the end.
728+
pub fn clear_attr_markers<'gc>(map: &mut indexmap::IndexMap<String, Value<'gc>>, key: &str) {
722729
map.shift_remove(&format!("{}{}", GETTER_PREFIX, key));
723730
map.shift_remove(&format!("{}{}", SETTER_PREFIX, key));
724731
map.shift_remove(&format!("{}{}{}", READONLY_PREFIX, key, READONLY_SUFFIX));

src/core/vm.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::core::opcode::{Chunk, Opcode};
22
use crate::core::property_descriptor::{
33
GETTER_PREFIX, NONCONFIGURABLE_PREFIX, NONCONFIGURABLE_SUFFIX, PropAttrs, PropDesc, PropKind, SETTER_PREFIX, attrs_from_legacy_map,
4-
desc_from_legacy_map, get_getter, has_getter, has_nonconfigurable_mark, has_nonenumerable_mark, has_readonly_mark, has_setter,
5-
lookup_getter, lookup_setter, make_getter_key, make_readonly_key, make_setter_key, mark_nonconfigurable, mark_nonenumerable,
6-
mark_readonly, read_attrs_from_legacy_map, remove_getter, remove_property_completely, remove_setter, set_getter, set_setter,
7-
unmark_nonconfigurable, unmark_nonenumerable, unmark_readonly, write_attrs_to_legacy_map,
4+
clear_attr_markers, desc_from_legacy_map, get_getter, has_getter, has_nonconfigurable_mark, has_nonenumerable_mark, has_readonly_mark,
5+
has_setter, lookup_getter, lookup_setter, make_getter_key, make_readonly_key, make_setter_key, mark_nonconfigurable,
6+
mark_nonenumerable, mark_readonly, read_attrs_from_legacy_map, remove_getter, remove_property_completely, remove_setter, set_getter,
7+
set_setter, unmark_nonconfigurable, unmark_nonenumerable, unmark_readonly, write_attrs_to_legacy_map,
88
};
99
use crate::core::value::{VmArrayData, VmMapData, VmSetData, value_to_string};
1010
use crate::core::{Collect, Expr, GcTrace, JSError, Value, new_gc_cell_ptr};

src/core/vm/runner.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4805,7 +4805,10 @@ impl<'gc> VM<'gc> {
48054805
}
48064806
// Write to per-closure overlay when available
48074807
let mut borrow = target_props.borrow_mut(ctx);
4808-
remove_property_completely(&mut borrow, &key);
4808+
// Clear attribute markers but keep the key in place so that
4809+
// IndexMap::insert updates the value in-place (preserving the
4810+
// original insertion order for keys like `length` / `name`).
4811+
clear_attr_markers(&mut borrow, &key);
48094812
borrow.insert(key, val.clone());
48104813
if let Value::VmFunction(fn_ip, _) | Value::VmClosure(fn_ip, _, _) = &val {
48114814
self.fn_home_objects.insert(*fn_ip, obj.clone());

0 commit comments

Comments
 (0)