Skip to content

Commit

Permalink
timers: refactor internal classes to ES2015 syntax
Browse files Browse the repository at this point in the history
PR-URL: #37408
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
ttzztztz authored Apr 4, 2022
1 parent 560cbc5 commit 9256728
Showing 1 changed file with 120 additions and 115 deletions.
235 changes: 120 additions & 115 deletions lib/internal/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ let timerListId = NumberMIN_SAFE_INTEGER;

const kRefed = Symbol('refed');

// Create a single linked list instance only once at startup
const immediateQueue = new ImmediateList();

let nextExpiry = Infinity;
let refCount = 0;

Expand All @@ -161,140 +158,148 @@ function initAsyncResource(resource, type) {
if (initHooksExist())
emitInit(asyncId, type, triggerAsyncId, resource);
}

// Timer constructor function.
// The entire prototype is defined in lib/timers.js
function Timeout(callback, after, args, isRepeat, isRefed) {
after *= 1; // Coalesce to number or NaN
if (!(after >= 1 && after <= TIMEOUT_MAX)) {
if (after > TIMEOUT_MAX) {
process.emitWarning(`${after} does not fit into` +
' a 32-bit signed integer.' +
'\nTimeout duration was set to 1.',
'TimeoutOverflowWarning');
class Timeout {
// Timer constructor function.
// The entire prototype is defined in lib/timers.js
constructor(callback, after, args, isRepeat, isRefed) {
after *= 1; // Coalesce to number or NaN
if (!(after >= 1 && after <= TIMEOUT_MAX)) {
if (after > TIMEOUT_MAX) {
process.emitWarning(`${after} does not fit into` +
' a 32-bit signed integer.' +
'\nTimeout duration was set to 1.',
'TimeoutOverflowWarning');
}
after = 1; // Schedule on next tick, follows browser behavior
}
after = 1; // Schedule on next tick, follows browser behavior
}

this._idleTimeout = after;
this._idlePrev = this;
this._idleNext = this;
this._idleStart = null;
// This must be set to null first to avoid function tracking
// on the hidden class, revisit in V8 versions after 6.2
this._onTimeout = null;
this._onTimeout = callback;
this._timerArgs = args;
this._repeat = isRepeat ? after : null;
this._destroyed = false;

if (isRefed)
incRefCount();
this[kRefed] = isRefed;
this[kHasPrimitive] = false;

initAsyncResource(this, 'Timeout');
}
this._idleTimeout = after;
this._idlePrev = this;
this._idleNext = this;
this._idleStart = null;
// This must be set to null first to avoid function tracking
// on the hidden class, revisit in V8 versions after 6.2
this._onTimeout = null;
this._onTimeout = callback;
this._timerArgs = args;
this._repeat = isRepeat ? after : null;
this._destroyed = false;

// Make sure the linked list only shows the minimal necessary information.
Timeout.prototype[inspect.custom] = function(_, options) {
return inspect(this, {
...options,
// Only inspect one level.
depth: 0,
// It should not recurse.
customInspect: false
});
};
if (isRefed)
incRefCount();
this[kRefed] = isRefed;
this[kHasPrimitive] = false;

Timeout.prototype.refresh = function() {
if (this[kRefed])
active(this);
else
unrefActive(this);
initAsyncResource(this, 'Timeout');
}

return this;
};
// Make sure the linked list only shows the minimal necessary information.
[inspect.custom](_, options) {
return inspect(this, {
...options,
// Only inspect one level.
depth: 0,
// It should not recurse.
customInspect: false
});
}

Timeout.prototype.unref = function() {
if (this[kRefed]) {
this[kRefed] = false;
if (!this._destroyed)
decRefCount();
refresh() {
if (this[kRefed])
active(this);
else
unrefActive(this);

return this;
}
return this;
};

Timeout.prototype.ref = function() {
if (!this[kRefed]) {
this[kRefed] = true;
if (!this._destroyed)
incRefCount();
unref() {
if (this[kRefed]) {
this[kRefed] = false;
if (!this._destroyed)
decRefCount();
}
return this;
}
return this;
};

Timeout.prototype.hasRef = function() {
return this[kRefed];
};
ref() {
if (!this[kRefed]) {
this[kRefed] = true;
if (!this._destroyed)
incRefCount();
}
return this;
}

function TimersList(expiry, msecs) {
this._idleNext = this; // Create the list with the linkedlist properties to
this._idlePrev = this; // Prevent any unnecessary hidden class changes.
this.expiry = expiry;
this.id = timerListId++;
this.msecs = msecs;
this.priorityQueuePosition = null;
hasRef() {
return this[kRefed];
}
}

// Make sure the linked list only shows the minimal necessary information.
TimersList.prototype[inspect.custom] = function(_, options) {
return inspect(this, {
...options,
// Only inspect one level.
depth: 0,
// It should not recurse.
customInspect: false
});
};
class TimersList {
constructor(expiry, msecs) {
this._idleNext = this; // Create the list with the linkedlist properties to
this._idlePrev = this; // Prevent any unnecessary hidden class changes.
this.expiry = expiry;
this.id = timerListId++;
this.msecs = msecs;
this.priorityQueuePosition = null;
}

// A linked list for storing `setImmediate()` requests
function ImmediateList() {
this.head = null;
this.tail = null;
// Make sure the linked list only shows the minimal necessary information.
[inspect.custom](_, options) {
return inspect(this, {
...options,
// Only inspect one level.
depth: 0,
// It should not recurse.
customInspect: false
});
}
}

// Appends an item to the end of the linked list, adjusting the current tail's
// next pointer and the item's previous pointer where applicable
ImmediateList.prototype.append = function(item) {
if (this.tail !== null) {
this.tail._idleNext = item;
item._idlePrev = this.tail;
} else {
this.head = item;
// A linked list for storing `setImmediate()` requests
class ImmediateList {
constructor() {
this.head = null;
this.tail = null;
}
this.tail = item;
};

// Removes an item from the linked list, adjusting the pointers of adjacent
// items and the linked list's head or tail pointers as necessary
ImmediateList.prototype.remove = function(item) {
if (item._idleNext) {
item._idleNext._idlePrev = item._idlePrev;
// Appends an item to the end of the linked list, adjusting the current tail's
// next pointer and the item's previous pointer where applicable
append(item) {
if (this.tail !== null) {
this.tail._idleNext = item;
item._idlePrev = this.tail;
} else {
this.head = item;
}
this.tail = item;
}

if (item._idlePrev) {
item._idlePrev._idleNext = item._idleNext;
}
// Removes an item from the linked list, adjusting the pointers of adjacent
// items and the linked list's head or tail pointers as necessary
remove(item) {
if (item._idleNext) {
item._idleNext._idlePrev = item._idlePrev;
}

if (item === this.head)
this.head = item._idleNext;
if (item === this.tail)
this.tail = item._idlePrev;
if (item._idlePrev) {
item._idlePrev._idleNext = item._idleNext;
}

item._idleNext = null;
item._idlePrev = null;
};
if (item === this.head)
this.head = item._idleNext;
if (item === this.tail)
this.tail = item._idlePrev;

item._idleNext = null;
item._idlePrev = null;
}
}

// Create a single linked list instance only once at startup
const immediateQueue = new ImmediateList();

function incRefCount() {
if (refCount++ === 0)
Expand Down

0 comments on commit 9256728

Please sign in to comment.