util: prevent tampering with internals in inspect()
· nodejs/node@5672ab7 (original) (raw)
`@@ -150,6 +150,16 @@ const meta = [
`
150
150
`'', '', '', '', '', '', '', '\\'
`
151
151
`];
`
152
152
``
``
153
`+
function getUserOptions(ctx) {
`
``
154
`+
const obj = { stylize: ctx.stylize };
`
``
155
`+
for (const key of Object.keys(inspectDefaultOptions)) {
`
``
156
`+
obj[key] = ctx[key];
`
``
157
`+
}
`
``
158
`+
if (ctx.userOptions === undefined)
`
``
159
`+
return obj;
`
``
160
`+
return { ...obj, ...ctx.userOptions };
`
``
161
`+
}
`
``
162
+
153
163
`/**
`
154
164
` * Echos the value of any input. Tries to print the value out
`
155
165
` * in the best way possible given the different types.
`
`@@ -192,8 +202,16 @@ function inspect(value, opts) {
`
192
202
`ctx.showHidden = opts;
`
193
203
`} else if (opts) {
`
194
204
`const optKeys = Object.keys(opts);
`
195
``
`-
for (var i = 0; i < optKeys.length; i++) {
`
196
``
`-
ctx[optKeys[i]] = opts[optKeys[i]];
`
``
205
`+
for (const key of optKeys) {
`
``
206
`+
// TODO(BridgeAR): Find a solution what to do about stylize. Either make
`
``
207
`+
// this function public or add a new API with a similar or better
`
``
208
`+
// functionality.
`
``
209
`+
if (hasOwnProperty(inspectDefaultOptions, key) || key === 'stylize') {
`
``
210
`+
ctx[key] = opts[key];
`
``
211
`+
} else if (ctx.userOptions === undefined) {
`
``
212
`+
// This is required to pass through the actual user input.
`
``
213
`+
ctx.userOptions = opts;
`
``
214
`+
}
`
197
215
`}
`
198
216
`}
`
199
217
`}
`
`@@ -522,14 +540,10 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
`
522
540
`maybeCustom !== inspect &&
`
523
541
`// Also filter out any prototype objects using the circular check.
`
524
542
`!(value.constructor && value.constructor.prototype === value)) {
`
525
``
`-
// Remove some internal properties from the options before passing it
`
526
``
`-
// through to the user function. This also prevents option manipulation.
`
527
``
`-
// eslint-disable-next-line no-unused-vars
`
528
``
`-
const { budget, seen, indentationLvl, ...plainCtx } = ctx;
`
529
543
`// This makes sure the recurseTimes are reported as before while using
`
530
544
`// a counter internally.
`
531
545
`const depth = ctx.depth === null ? null : ctx.depth - recurseTimes;
`
532
``
`-
const ret = maybeCustom.call(context, depth, plainCtx);
`
``
546
`+
const ret = maybeCustom.call(context, depth, getUserOptions(ctx));
`
533
547
`` // If the custom inspection method returned this
, don't go into
``
534
548
`// infinite recursion.
`
535
549
`if (ret !== context) {
`