Skip to content

Add Object::getPropertyNameIDs to JSI - #2318

Draft
tsapeta wants to merge 1 commit into
meta:static_hfrom
tsapeta:tsapeta/property-name-ids
Draft

tsapeta wants to merge 1 commit into
meta:static_hfrom
tsapeta:tsapeta/property-name-ids

Conversation

@tsapeta

@tsapeta tsapeta commented Nov 13, 2026 •

Copy link
Copy Markdown

Summary

React Native reads every props object with Object::getPropertyNames, then getValueAtIndex, getString, getProperty(String) and utf8 for each name. In Hermes, for-in keeps the names of ordinary objects as symbols, so this converts each symbol to a string, wraps it in a JS array, reads it back, and converts the string to a symbol again for the property lookup.

This adds getPropertyNameIDs to JSI:

// IRuntime
virtual std::vector<PropNameID> getPropertyNameIDs(const Object& object) = 0;
// Object
std::vector<PropNameID> getPropertyNameIDs(IRuntime& runtime) const;

It returns the same names as getPropertyNames, in the same order, as PropNameIDs and without a JS array.

  • It follows getStringData and setPrototypeOf: an IRuntime method with a default implementation in jsi::Runtime (jsi.cpp), built on getPropertyNames, so every runtime has it.
  • RuntimeDecorator forwards it, and WithRuntimeDecorator forwards it inside Around, so the thread-safe runtime takes its lock.
  • TracingRuntime uses the default implementation, so a trace records the getPropertyNames and other calls that it's equivalent to, and replay doesn't need a new event.
  • Hermes returns the for-in symbols directly, and converts only string and index keys with stringToSymbolID (index keys with numberToStringPrimitive first). The values can then be read with getProperty(PropNameID), which looks the symbol up directly.

#2319 (forEachProperty) adds a walk that also reads the values and gives UTF-8 names, for callers that read each name once. This one is for callers that keep the names, for example to read the same properties again with getProperty.

Test Plan

  • New JSITest.GetPropertyNameIDsTest in jsi/test/testlib.cpp, for the runtime's implementation and, through a RuntimeDecorator, for the default one: for objects with string, index, non-ASCII, symbol, inherited, getter and non-enumerable properties, an array and an empty object, the names and getProperty values are the same as with getPropertyNames.
  • APITests: all 439 tests pass. hermesABIRuntimeWrapper, hermesSandboxRuntime, synthTrace and traceInterpreter build.
  • A timing loop on top of APITests (macOS host, Release, median of 9 samples of 200,000 iterations, not part of this PR) for the walk React Native does: names, values and UTF-8 names, on objects with number-valued props.
Walk makeHermesRuntime makeThreadSafeHermesRuntime
getPropertyNames + strings, 1 prop 97 ns 154 ns
getPropertyNameIDs, 1 prop 46 ns 82 ns
getPropertyNames + strings, 6 props 477 ns 702 ns
getPropertyNameIDs, 6 props 173 ns 325 ns
getPropertyNames + strings, 20 props 1,534 ns 2,356 ns
getPropertyNameIDs, 20 props 551 ns 1,143 ns

#2317 makes the getPropertyNames walk about 45% faster on its own; with both, the PropNameID walk is still about a third faster than the string walk.

@meta-cla meta-cla Bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Nov 13, 2026
getPropertyNameIDs returns the names of the enumerable properties of an object as PropNameIDs, in the order of getPropertyNames, without creating a JS array. It's an IRuntime method with a default implementation in jsi::Runtime, built on getPropertyNames, like getStringData. The decorators forward it, and TracingRuntime uses the default implementation, so traces record the calls that it's equivalent to.

Hermes keeps the for-in names of ordinary objects as symbols, so it returns them directly instead of converting them to strings, and the property values can be read with getProperty(PropNameID) without converting the names back.
@tsapeta
tsapeta force-pushed the tsapeta/property-name-ids branch from 6102915 to 9026353 Compare November 13, 2026 10:27
@tsapeta tsapeta changed the title Add a JSI interface to get property names as PropNameIDs Add Object::getPropertyNameIDs to JSI Nov 13, 2026
@tsapeta tsapeta changed the title Add Object::getPropertyNameIDs to JSI Add Object::getPropertyNameIDs to JSI Nov 13, 2026
@tsapeta
tsapeta marked this pull request as ready for review November 13, 2026 11:18
@tmikov

tmikov commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

This breaks the ABI like #2319. Worth discussing whether two separate calls for essentially the same thing are needed.

@tsapeta
tsapeta marked this pull request as draft November 13, 2026 17:58

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Do not delete this pull request or issue due to inactivity.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants