Skip to content

Commit 9549e2d

Browse files
committed
lib: use Object.create(null) directly
After V8 5.6, using Object.create(null) directly is now faster than using a constructor. Refs: emberjs/ember.js#15001 Refs: https://crrev.com/532c16eca071df3ec8eed394dcebb932ef584ee6
1 parent db2f056 commit 9549e2d

File tree

6 files changed

+19
-34
lines changed

6 files changed

+19
-34
lines changed

lib/_http_outgoing.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const common = require('_http_common');
3131
const checkIsHttpToken = common._checkIsHttpToken;
3232
const checkInvalidHeaderChar = common._checkInvalidHeaderChar;
3333
const outHeadersKey = require('internal/http').outHeadersKey;
34-
const StorageObject = require('internal/querystring').StorageObject;
3534

3635
const CRLF = common.CRLF;
3736
const debug = common.debug;
@@ -143,7 +142,7 @@ Object.defineProperty(OutgoingMessage.prototype, '_headerNames', {
143142
get: function() {
144143
const headers = this[outHeadersKey];
145144
if (headers) {
146-
const out = new StorageObject();
145+
const out = Object.create(null);
147146
const keys = Object.keys(headers);
148147
for (var i = 0; i < keys.length; ++i) {
149148
const key = keys[i];
@@ -552,7 +551,7 @@ OutgoingMessage.prototype.getHeaderNames = function getHeaderNames() {
552551
// Returns a shallow copy of the current outgoing headers.
553552
OutgoingMessage.prototype.getHeaders = function getHeaders() {
554553
const headers = this[outHeadersKey];
555-
const ret = new StorageObject();
554+
const ret = Object.create(null);
556555
if (headers) {
557556
const keys = Object.keys(headers);
558557
for (var i = 0; i < keys.length; ++i) {

lib/events.js

+7-13
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@
2323

2424
var domain;
2525

26-
// This constructor is used to store event handlers. Instantiating this is
27-
// faster than explicitly calling `Object.create(null)` to get a "clean" empty
28-
// object (tested with v8 v4.9).
29-
function EventHandlers() {}
30-
EventHandlers.prototype = Object.create(null);
31-
3226
function EventEmitter() {
3327
EventEmitter.init.call(this);
3428
}
@@ -71,7 +65,7 @@ EventEmitter.init = function() {
7165
}
7266

7367
if (!this._events || this._events === Object.getPrototypeOf(this)._events) {
74-
this._events = new EventHandlers();
68+
this._events = Object.create(null);
7569
this._eventsCount = 0;
7670
}
7771

@@ -241,7 +235,7 @@ function _addListener(target, type, listener, prepend) {
241235

242236
events = target._events;
243237
if (!events) {
244-
events = target._events = new EventHandlers();
238+
events = target._events = Object.create(null);
245239
target._eventsCount = 0;
246240
} else {
247241
// To avoid recursion in the case that type === "newListener"! Before
@@ -356,7 +350,7 @@ EventEmitter.prototype.removeListener =
356350

357351
if (list === listener || list.listener === listener) {
358352
if (--this._eventsCount === 0)
359-
this._events = new EventHandlers();
353+
this._events = Object.create(null);
360354
else {
361355
delete events[type];
362356
if (events.removeListener)
@@ -379,7 +373,7 @@ EventEmitter.prototype.removeListener =
379373
if (list.length === 1) {
380374
list[0] = undefined;
381375
if (--this._eventsCount === 0) {
382-
this._events = new EventHandlers();
376+
this._events = Object.create(null);
383377
return this;
384378
} else {
385379
delete events[type];
@@ -408,11 +402,11 @@ EventEmitter.prototype.removeAllListeners =
408402
// not listening for removeListener, no need to emit
409403
if (!events.removeListener) {
410404
if (arguments.length === 0) {
411-
this._events = new EventHandlers();
405+
this._events = Object.create(null);
412406
this._eventsCount = 0;
413407
} else if (events[type]) {
414408
if (--this._eventsCount === 0)
415-
this._events = new EventHandlers();
409+
this._events = Object.create(null);
416410
else
417411
delete events[type];
418412
}
@@ -428,7 +422,7 @@ EventEmitter.prototype.removeAllListeners =
428422
this.removeAllListeners(key);
429423
}
430424
this.removeAllListeners('removeListener');
431-
this._events = new EventHandlers();
425+
this._events = Object.create(null);
432426
this._eventsCount = 0;
433427
return this;
434428
}

lib/fs.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ const internalUtil = require('internal/util');
4343
const assertEncoding = internalFS.assertEncoding;
4444
const stringToFlags = internalFS.stringToFlags;
4545
const getPathFromURL = internalURL.getPathFromURL;
46-
const { StorageObject } = require('internal/querystring');
4746

4847
Object.defineProperty(exports, 'constants', {
4948
configurable: false,
@@ -1560,7 +1559,7 @@ if (isWindows) {
15601559
nextPart = function nextPart(p, i) { return p.indexOf('/', i); };
15611560
}
15621561

1563-
const emptyObj = new StorageObject();
1562+
const emptyObj = Object.create(null);
15641563
fs.realpathSync = function realpathSync(p, options) {
15651564
if (!options)
15661565
options = emptyObj;
@@ -1580,8 +1579,8 @@ fs.realpathSync = function realpathSync(p, options) {
15801579
return maybeCachedResult;
15811580
}
15821581

1583-
const seenLinks = new StorageObject();
1584-
const knownHard = new StorageObject();
1582+
const seenLinks = Object.create(null);
1583+
const knownHard = Object.create(null);
15851584
const original = p;
15861585

15871586
// current character position in p
@@ -1700,8 +1699,8 @@ fs.realpath = function realpath(p, options, callback) {
17001699
return;
17011700
p = pathModule.resolve(p);
17021701

1703-
const seenLinks = new StorageObject();
1704-
const knownHard = new StorageObject();
1702+
const seenLinks = Object.create(null);
1703+
const knownHard = Object.create(null);
17051704

17061705
// current character position in p
17071706
var pos;

lib/internal/querystring.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,7 @@ const isHexTable = [
2323
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // ... 256
2424
];
2525

26-
// Instantiating this is faster than explicitly calling `Object.create(null)`
27-
// to get a "clean" empty object (tested with v8 v4.9).
28-
function StorageObject() {}
29-
StorageObject.prototype = Object.create(null);
30-
3126
module.exports = {
3227
hexTable,
33-
isHexTable,
34-
StorageObject
28+
isHexTable
3529
};

lib/querystring.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
const { Buffer } = require('buffer');
2727
const {
28-
StorageObject,
2928
hexTable,
3029
isHexTable
3130
} = require('internal/querystring');
@@ -281,7 +280,7 @@ const defEqCodes = [61]; // =
281280

282281
// Parse a key/val string.
283282
function parse(qs, sep, eq, options) {
284-
const obj = new StorageObject();
283+
const obj = Object.create(null);
285284

286285
if (typeof qs !== 'string' || qs.length === 0) {
287286
return obj;

lib/url.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
const { toASCII } = process.binding('config').hasIntl ?
2525
process.binding('icu') : require('punycode');
26-
const { StorageObject, hexTable } = require('internal/querystring');
26+
const { hexTable } = require('internal/querystring');
2727
const internalUrl = require('internal/url');
2828
exports.parse = urlParse;
2929
exports.resolve = urlResolve;
@@ -197,7 +197,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
197197
}
198198
} else if (parseQueryString) {
199199
this.search = '';
200-
this.query = new StorageObject();
200+
this.query = Object.create(null);
201201
}
202202
return this;
203203
}
@@ -390,7 +390,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
390390
} else if (parseQueryString) {
391391
// no query string, but parseQueryString still requested
392392
this.search = '';
393-
this.query = new StorageObject();
393+
this.query = Object.create(null);
394394
}
395395

396396
var firstIdx = (questionIdx !== -1 &&

0 commit comments

Comments
 (0)