Context
PR #413 fixed the Array(arr) branch in interpreter/runtime/property.mbt's get_computed_property_impl — it was checking symbol_properties directly without first consulting symbol_descriptors for getter-type (accessor) entries. The same gap exists in the Promise(data) branch and was not addressed in that PR.
Identified during the PR #413 post-merge analysis.
Problem
In interpreter/runtime/property.mbt, the per-variant dispatch in get_computed_property_impl follows this two-step protocol for own symbol property lookup:
- Check
symbol_descriptors for an accessor descriptor (getter). If a getter is present, call it.
- Check
symbol_properties for a data value.
The Object, Map, and Set branches all follow this protocol. The Array branch was fixed in PR #413. The Promise(data) branch (currently around line 1031) only performs step 2 — it reads data.bag.symbol_properties directly and skips data.bag.symbol_descriptors entirely:
Promise(data) => {
match data.bag.symbol_properties.get(sym.id) { // step 2 only — missing step 1
Some(v) => return v
None => ()
}
...
}
This means if a Promise instance has an accessor-type own symbol property (e.g., a getter installed on its bag.symbol_descriptors), the getter will be silently skipped and the property will read as absent.
Current severity: Low — no code path in the engine currently installs getter-type symbol properties on individual Promise instances. However, this will become exploitable as Proxy wrapping and future spec features (Observable, async iterator protocol extensions) create Promise-like objects with intercepted symbol access.
Suggested work
Mirror the fix applied to Array(arr) in PR #413. Before the existing symbol_properties lookup in the Promise(data) branch, add a symbol_descriptors accessor check:
Promise(data) => {
// Check for accessor descriptor (getter) on own symbol property.
match data.bag.symbol_descriptors.get(sym.id) {
Some(desc) =>
match desc.getter {
Some(getter) => return self.call_value(getter, obj, [], loc)
None => ()
}
None => ()
}
// Check promise's own symbol property bag.
match data.bag.symbol_properties.get(sym.id) {
Some(v) => return v
None => ()
}
...
}
Also audit whether the has_property path for Promise(data) has the same gap (line ~665 area — the hasOwnProperty implementation), and whether set_computed_property_impl needs a matching fix for the setter side.
Acceptance criteria
get_computed_property_impl Promise(data) branch checks symbol_descriptors before symbol_properties
- All existing Promise tests still pass (1272/1272)
moon test clean
- A whitebox test in
interpreter/runtime/ pins the behavior: a Promise instance with a getter-type symbol descriptor correctly fires the getter
Context
PR #413 fixed the
Array(arr)branch ininterpreter/runtime/property.mbt'sget_computed_property_impl— it was checkingsymbol_propertiesdirectly without first consultingsymbol_descriptorsfor getter-type (accessor) entries. The same gap exists in thePromise(data)branch and was not addressed in that PR.Identified during the PR #413 post-merge analysis.
Problem
In
interpreter/runtime/property.mbt, the per-variant dispatch inget_computed_property_implfollows this two-step protocol for own symbol property lookup:symbol_descriptorsfor an accessor descriptor (getter). If a getter is present, call it.symbol_propertiesfor a data value.The Object, Map, and Set branches all follow this protocol. The Array branch was fixed in PR #413. The
Promise(data)branch (currently around line 1031) only performs step 2 — it readsdata.bag.symbol_propertiesdirectly and skipsdata.bag.symbol_descriptorsentirely:This means if a Promise instance has an accessor-type own symbol property (e.g., a getter installed on its
bag.symbol_descriptors), the getter will be silently skipped and the property will read as absent.Current severity: Low — no code path in the engine currently installs getter-type symbol properties on individual Promise instances. However, this will become exploitable as Proxy wrapping and future spec features (Observable, async iterator protocol extensions) create Promise-like objects with intercepted symbol access.
Suggested work
Mirror the fix applied to
Array(arr)in PR #413. Before the existingsymbol_propertieslookup in thePromise(data)branch, add asymbol_descriptorsaccessor check:Also audit whether the
has_propertypath forPromise(data)has the same gap (line ~665 area — thehasOwnPropertyimplementation), and whetherset_computed_property_implneeds a matching fix for the setter side.Acceptance criteria
get_computed_property_implPromise(data)branch checkssymbol_descriptorsbeforesymbol_propertiesmoon testcleaninterpreter/runtime/pins the behavior: a Promise instance with a getter-type symbol descriptor correctly fires the getter