Skip to content

Stage 2 preparation #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
152 changes: 152 additions & 0 deletions slides/07.2025 - stage_2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
marp: true
title: "ECMAScript Proposal: `Object.propertyCount`"
description: TC39 Proposal – July 2025
paginate: true
---

# ECMAScript Proposal: `Object.propertyCount`

### Update

Champion: Ruben Bridgewater, Jordan Harband

Author: Ruben Bridgewater <[email protected]>

Stage: 1

---

## Overview / Problem Statement

As described last time: Object.propertyCount proposal is mainly there to overcome *performance* and *correctness* issues in a variety of use cases / algorithms.

Use cases highlighted were:

1. Input validation (e.g., guarding against too big input)
2. Object comparison
3. Faster telemetry data
4. Testing utility
5. General fast paths for many different algorithms
6. Detecting non-index properties on array like objects
7. Sparse array detection

---

## Precedent

Frequent patterns in widely-used JavaScript runtimes, frameworks, and libraries (Node.js, React, Angular, Lodash) demonstrate the common need for an optimized property counting mechanism.

The regular expression exec/match/matchAll methods produce a "match object" that is an Array, with non-index string properties on it (lastIndex, groups, etc).

---

## Examples

### Only enumerable symbols (needs the enumerable ones)

- [*Next.js*](https://github.com/vercel/next.js/blob/82ab39f8017e2ba1aef668269e5b68cdea94f335/packages/next/src/compiled/%40babel/runtime/helpers/objectSpread.js#L7-L9)
- [*Angular*](https://github.com/angular/angular/blob/6fa8d441979fdbabb88dddd246f54587e17126e8/packages/zone.js/lib/browser/define-property.ts#L48-L60)
- [*TypeScript*](https://github.com/microsoft/TypeScript/blob/83dc0bb2ed91fe0815ab28dc3ff95fae7425e413/src/compiler/factory/emitHelpers.ts#L905-L908)
- [*Lodash*](https://github.com/lodash/lodash/blob/8a26eb42adb303f4adc7ef56e300f14c5992aa68/dist/lodash.js#L6075-L6083)

### Any symbol (length only)

- [*React*](https://github.com/facebook/react/blob/336614679600af371b06371c0fbdd31fd9838231/packages/react-server/src/ReactFlightServer.js#L2787-L2788)
- [*Next.js*](https://github.com/vercel/next.js/blob/82ab39f8017e2ba1aef668269e5b68cdea94f335/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js#L685-L686)

### Any non symbol property (length only)

- [*React*](https://github.com/facebook/react/blob/336614679600af371b06371c0fbdd31fd9838231/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L4425)

---

## Examples 2

### Any property (symbol & non-symbol; length only)

- [*VS Code*](https://github.com/microsoft/vscode/blob/a32a31b6ea1e1bc92504879d7ce96ad53e43ef2c/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts#L1066-L1069)

### Any non-symbol reflects Object.keys depending on the enumerability

### Array index (checks if it is a valid index)

- Lodash https://github.com/lodash/lodash/blob/main/dist/lodash.core.js#L1364-L1380
- Node.js assert.deepStrictEqual / partialDeepStrictEqual / ...
- Node.js console.log / util.inspect

---

## Intermediate Conclusion

Frequent use cases next to the most common (enumerable strings) one are:

1. Symbol checks
2. Enumerability for symbols
3. Index properties

---

## Simplified proposal

Separating specific use cases from the proposal:

- Detecting non-index properties on array like objects
- Sparse array detection

The new proposals all provide benefit on their own, while allowing to move this proposal forward independently.
That way the main use case is immediately addressed.
Combined, the proposals provide even more benefit by allowing to optimize even more algorithms.

---

## Benefit

1. Differentiating non index string properties vs other string properties is difficult (TypedArray vs. Array).
2. Explicit dense / sparse array detection instead of implicit one

---

## Explicit Semantics as before

- Only own properties are considered.
- Enumerability explicitly defined by the `enumerable` parameter.
- Avoids intermediate array allocation entirely when implemented natively.

---

## Algorithmic Specification (details in [spec proposal](./spec.emu))

1. Initialize a numeric property counter to `0`.
2. Iterate directly over the object's own property descriptors
- Access the internal property keys directly via the object's internal slots.
- For each own property:
- Determine if the key is a string or a symbol.
- Check if the property type matches any specified in `keyTypes`.
- If `enumerable` is not `'all'`, match the property's enumerability against the provided boolean value.
- If the property meets all criteria, increment the counter.
3. Return the final count value.

---

## Use Cases

- Improved readability and explicit intent
- Significant **performance** gains
- **Reduced memory** overhead
- **Simpler code**

---

## Conclusion

`Object.propertyCount` offers substantial performance benefits by efficiently counting object properties, enhancing ECMAScript with clarity, performance, and reduced memory overhead.

---

## Next steps

- Getting input about the separation
- Naming
- Addressing further comments
- Stage 2 or 2.7?
Binary file added slides/07.2025 - stage_2.pdf
Binary file not shown.