Uh oh!
There was an error while loading. Please reload this page.
lib: add internalUtil.kEmptyObject - #43159
Conversation
nodejs-github-bot
commented
May 20, 2022
Review requested:
|
What if our own code later assigns to a defaulted-to nullObject? It won't throw and the assignment will be lost. Do we enforce not modifying parameters through lint rules? Should we when nullObject was used? |
LiviaMedeiros
commented
May 20, 2022
I believe assignment to a frozen object throws in strict mode? Are there places where it doesn't? Of course this object is not supposed to be exposed to usedland in any way, nor used in any scenario where there is a slightest chance to mutate it. |
panva
commented
May 20, 2022
I only tried with likewise constructed null object in REPL. |
LiviaMedeiros
commented
May 20, 2022
It throws for me in REPL as well: Welcome to Node.js v18.1.0.Type ".help" for more information.
> Object.assign(Object.freeze(Object.create(null)), { blep: 'blop' });Uncaught TypeError: Cannot add property blep, object is not extensible at Function.assign (<anonymous>) |
aduh95
commented
May 20, 2022
Maybe it should be named |
internalUtil.nullObjectinternalUtil.kEmptyObjectLiviaMedeiros
commented
May 20, 2022
Sure, renamed. I'm still tracing some tangled places in |
panva
commented
May 20, 2022
Trying a simpler approach, one that could be more likely used. >o=Object.freeze(Object.create(null))[Object: nullprototype]{}>o.foo='bar''bar'>o.fooundefined |
LiviaMedeiros
commented
May 20, 2022
Right, it doesn't run in strict mode by default. 😅 $ node --use_strictWelcome to Node.js v18.1.0.Type ".help" for more information.
> const o = Object.freeze(Object.create(null));undefined
> o.blep = 'blop';Uncaught TypeError: Cannot add property blep, object is not extensibleBoth approaches are covered by test: https://github.com/nodejs/node/blob/5e914f263866f5f22a647e92060c1ed36e4d3300/test/parallel/test-internal-util-objects.js#L76-L87 |
panva
commented
May 20, 2022
Thank you for your diligence. I've learned something ;) |
mcollina
left a comment
There was a problem hiding this comment.
I highly suspect this will cause major performance regressions as frozen objects are slower than their traditional counterparts.
This should be deeply investigated for regressions before landing.
LiviaMedeiros
commented
May 21, 2022
AFAIK performance hit from freezing was a thing in the past, but in modern v8 there's no difference anymore. Synthetic testing on 18.1.0 and master shows [fastest] To be safe, it would make sense to not backport this.
Aside from |
Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1142/ EDIT: there are a few benchmark impacted by this change, overall it's pretty mild though: Full resullts |
mcollina
commented
May 21, 2022
Amazing progress, I might have missed it. Have you got a link? |
Not 100% sure if these are exhaustive or there were follow-ups: (for my tests I ran destructuring, not iterating) Edit: according to https://bugs.chromium.org/p/chromium/issues/detail?id=980227, there still are issues with some particular operations. I tried to benchmark their 1000-element array in Chromium and got this (higher is better):
But these operations shouldn't be applicable to this partucular empty object. |
5fea108 to
ae13f10Compare
This comment was marked as outdated.
This comment was marked as outdated.
LiviaMedeiros
commented
May 22, 2022
CITGM: https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/2939/ Just in case of some sort of really elusive errors. |
nodejs-github-bot
commented
May 22, 2022
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
aduh95
commented
Jun 11, 2022
Landed in e227e52...917fcb2 |
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: #43159 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Problem
There are lots of places in core where we have to pass an optional "pre-ES6 map"-style object with optional properties.
To avoid verbose boilerplate code or overusing of optional chaining, and to allow destructuring, we need a fallback value of
{}, thus creating a throwaway object:It is also highly affected by prototype tampering, e.g.
So we have to prefer
Object.create(null), which is slower and still creates a throwaway object on every usage.Solution
A single immutable object that guarantees any property to be
undefined.