Commit e99ad16
authored
perf(shared): skip defineProperty for non-inherited keys and make clone cycle-safe (#1994)
`set`, `clone`, and `mergeTwoLevels` in `@orpc/shared` wrote every
property through `Object.defineProperty`, which is several times slower
than a plain assignment. Assignment creates the same own property for
every key except `__proto__`, so the helper now assigns directly and
only uses `Object.defineProperty` for that key. The helper is renamed
from `defineOwnProperty` to `setOwn` to pair with `getOwn`. `clone` also
now survives circular input instead of overflowing the stack.
## Performance
- Building an 8-key object two million times drops from about 4 s to
about 0.5 s, roughly 8x faster.
- The common path is one string comparison followed by a plain write.
## Safety
- Prototype pollution guards are unchanged: the walk in `set` still
descends only into own properties, so `constructor.prototype` and
`__proto__` paths never reach `Object.prototype`.
- `__proto__` is the only accessor on `Object.prototype`, so it is the
only key where assignment and an own property differ. It still lands as
an own data property instead of re-parenting the object.
## Fixes
- `clone` no longer recurses forever on self-referencing arrays or
objects. Cycles become cycles in the copy, and a value referenced from
several places is cloned once and stays shared.
## Testing
- New tests: `clone` on circular and shared-reference input.
- Shared object tests plus the callers in contract, trpc, and server
pass; eslint and a type check of `packages/shared` including test files
are clean.1 parent d637f30 commit e99ad16
2 files changed
Lines changed: 84 additions & 15 deletions
File tree
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
412 | 412 | | |
413 | 413 | | |
414 | 414 | | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
415 | 450 | | |
416 | 451 | | |
417 | 452 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
110 | | - | |
| 110 | + | |
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
| 118 | + | |
119 | 119 | | |
120 | 120 | | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
128 | 136 | | |
129 | 137 | | |
130 | 138 | | |
| |||
148 | 156 | | |
149 | 157 | | |
150 | 158 | | |
151 | | - | |
| 159 | + | |
152 | 160 | | |
153 | 161 | | |
154 | 162 | | |
| |||
168 | 176 | | |
169 | 177 | | |
170 | 178 | | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
171 | 183 | | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
172 | 188 | | |
173 | | - | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
174 | 202 | | |
175 | 203 | | |
176 | 204 | | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
177 | 210 | | |
| 211 | + | |
178 | 212 | | |
179 | | - | |
| 213 | + | |
180 | 214 | | |
181 | | - | |
| 215 | + | |
182 | 216 | | |
183 | 217 | | |
184 | 218 | | |
185 | | - | |
| 219 | + | |
186 | 220 | | |
187 | 221 | | |
188 | | - | |
| 222 | + | |
189 | 223 | | |
190 | 224 | | |
191 | 225 | | |
| |||
0 commit comments