From 0c11a17d821b506380c5e1e94cd4167f86e1b1fe Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 1 Jan 2021 17:58:25 +0100 Subject: [PATCH] console: refactor to avoid unsafe array iteration PR-URL: https://github.com/nodejs/node/pull/36753 Reviewed-By: James M Snell --- lib/internal/console/constructor.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/internal/console/constructor.js b/lib/internal/console/constructor.js index dc2817ad2a54ec..2478991e5f682d 100644 --- a/lib/internal/console/constructor.js +++ b/lib/internal/console/constructor.js @@ -6,6 +6,7 @@ const { ArrayFrom, ArrayIsArray, + ArrayPrototypeForEach, ArrayPrototypePush, ArrayPrototypeUnshift, Boolean, @@ -19,7 +20,10 @@ const { ObjectKeys, ObjectPrototypeHasOwnProperty, ObjectValues, + ReflectApply, + ReflectConstruct, ReflectOwnKeys, + SafeArrayIterator, SafeMap, SafeWeakMap, StringPrototypeIncludes, @@ -97,7 +101,7 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) { // with new, because we need to define a custom instanceof to accommodate // the global console. if (!new.target) { - return new Console(...arguments); + return ReflectConstruct(Console, arguments); } if (!options || typeof options.write === 'function') { @@ -147,8 +151,7 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) { } // Bind the prototype functions to this Console instance - const keys = ObjectKeys(Console.prototype); - for (const key of keys) { + ArrayPrototypeForEach(ObjectKeys(Console.prototype), (key) => { // We have to bind the methods grabbed from the instance instead of from // the prototype so that users extending the Console can override them // from the prototype chain of the subclass. @@ -156,7 +159,7 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) { ObjectDefineProperty(this[key], 'name', { value: key }); - } + }); this[kBindStreamsEager](stdout, stderr); this[kBindProperties](ignoreErrors, colorMode, groupIndentation); @@ -320,14 +323,16 @@ ObjectDefineProperties(Console.prototype, { ...consolePropAttributes, value: function(args) { const opts = this[kGetInspectOptions](this._stdout); - return formatWithOptions(opts, ...args); + ArrayPrototypeUnshift(args, opts); + return ReflectApply(formatWithOptions, null, args); } }, [kFormatForStderr]: { ...consolePropAttributes, value: function(args) { const opts = this[kGetInspectOptions](this._stderr); - return formatWithOptions(opts, ...args); + ArrayPrototypeUnshift(args, opts); + return ReflectApply(formatWithOptions, null, args); } }, }); @@ -412,7 +417,8 @@ const consoleMethods = { assert(expression, ...args) { if (!expression) { args[0] = `Assertion failed${args.length === 0 ? '' : `: ${args[0]}`}`; - this.warn(...args); // The arguments will be formatted in warn() again + // The arguments will be formatted in warn() again + ReflectApply(this.warn, this, args); } }, @@ -458,7 +464,7 @@ const consoleMethods = { group(...data) { if (data.length > 0) { - this.log(...data); + ReflectApply(this.log, this, data); } this[kGroupIndent] += StringPrototypeRepeat(' ', this[kGroupIndentationWidth]); @@ -603,7 +609,7 @@ function timeLogImpl(self, name, label, data) { if (data === undefined) { self.log('%s: %s', label, formatted); } else { - self.log('%s: %s', label, formatted, ...data); + self.log('%s: %s', label, formatted, ...new SafeArrayIterator(data)); } return true; } @@ -630,10 +636,10 @@ function formatTime(ms) { } if (hours !== 0 || minutes !== 0) { - [seconds, ms] = StringPrototypeSplit( + ({ 0: seconds, 1: ms } = StringPrototypeSplit( NumberPrototypeToFixed(seconds, 3), '.' - ); + )); const res = hours !== 0 ? `${hours}:${pad(minutes)}` : minutes; return `${res}:${pad(seconds)}.${ms} (${hours !== 0 ? 'h:m' : ''}m:ss.mmm)`; }