From fa7a1c44b48563f0762479469d3d03bc42710c47 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 5 Dec 2024 14:10:45 -0500 Subject: [PATCH] fix(ses): Consistently name console methods Ref #2643 Ref 5e8fd33e7c9bf23b12640022a5ca4b11c29d0136 --- packages/ses/src/error/console.js | 61 +++++++++++++++++-------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/packages/ses/src/error/console.js b/packages/ses/src/error/console.js index 5151a609a3..44259e725c 100644 --- a/packages/ses/src/error/console.js +++ b/packages/ses/src/error/console.js @@ -28,6 +28,20 @@ import { * @import {ErrorInfo, ErrorInfoKind, LogRecord, NoteCallback, LoggedErrorHandler, MakeCausalConsole, MakeLoggingConsoleKit} from "./internal-types.js"; */ +/** + * Explicitly set a function's name, supporting use of arrow functions for which + * source text doesn't include a name and no initial name is set by + * NamedEvaluation + * https://tc39.es/ecma262/multipage/syntax-directed-operations.html#sec-runtime-semantics-namedevaluation + * Instead, we hope that tooling uses only the explicit `name` property. + * + * @template {function} T + * @param {string} name + * @param {T} fn + * @returns {T} + */ +const defineName = (name, fn) => defineProperty(fn, 'name', { value: name }); + // For our internal debugging purposes, uncomment // const internalDebugConsole = console; @@ -159,16 +173,12 @@ export const makeLoggingConsoleKit = ( const loggingConsole = fromEntries( arrayMap(consoleMethodPermits, ([name, _]) => { - // Use an arrow function so that it doesn't come with its own name in - // its printed form. Instead, we're hoping that tooling uses only - // the `.name` property set below. /** * @param {...any} args */ - const method = (...args) => { + const method = defineName(name, (...args) => { arrayPush(logArray, [name, ...args]); - }; - defineProperty(method, 'name', { value: name }); + }); return [name, freeze(method)]; }), ); @@ -370,7 +380,7 @@ export const makeCausalConsole = (baseConsole, loggedErrorHandler) => { /** * @param {...any} logArgs */ - const levelMethod = (...logArgs) => { + const levelMethod = defineName(level, (...logArgs) => { const subErrors = []; const argTags = extractErrorArgs(logArgs, subErrors); if (baseConsole[level]) { @@ -379,8 +389,7 @@ export const makeCausalConsole = (baseConsole, loggedErrorHandler) => { } // @ts-expect-error ConsoleProp vs LogSeverity mismatch logSubErrors(level, subErrors); - }; - defineProperty(levelMethod, 'name', { value: level }); + }); return [level, freeze(levelMethod)]; }); const otherMethodNames = arrayFilter( @@ -391,13 +400,12 @@ export const makeCausalConsole = (baseConsole, loggedErrorHandler) => { /** * @param {...any} args */ - const otherMethod = (...args) => { + const otherMethod = defineName(name, (...args) => { // @ts-ignore // eslint-disable-next-line @endo/no-polymorphic-call baseConsole[name](...args); return undefined; - }; - defineProperty(otherMethod, 'name', { value: name }); + }); return [name, freeze(otherMethod)]; }); @@ -458,23 +466,21 @@ export const defineCausalConsoleFromLogger = loggedErrorHandler => { } return tlogger(...args); }; - const makeNamed = (name, fn) => - ({ [name]: (...args) => fn(...args) })[name]; const baseConsole = fromEntries([ ...arrayMap(consoleLevelMethods, ([name]) => [ name, - makeNamed(name, logWithIndent), + defineName(name, (...args) => logWithIndent(...args)), ]), ...arrayMap(consoleOtherMethods, ([name]) => [ name, - makeNamed(name, (...args) => logWithIndent(name, ...args)), + defineName(name, (...args) => logWithIndent(name, ...args)), ]), ]); // https://console.spec.whatwg.org/#grouping for (const name of ['group', 'groupCollapsed']) { if (baseConsole[name]) { - baseConsole[name] = makeNamed(name, (...args) => { + baseConsole[name] = defineName(name, (...args) => { if (args.length >= 1) { // Prefix the logged data with "group" or "groupCollapsed". logWithIndent(...args); @@ -484,16 +490,17 @@ export const defineCausalConsoleFromLogger = loggedErrorHandler => { arrayPush(indents, ' '); }); } else { - baseConsole[name] = () => {}; + baseConsole[name] = defineName(name, () => {}); } } - if (baseConsole.groupEnd) { - baseConsole.groupEnd = makeNamed('groupEnd', (...args) => { - arrayPop(indents); - }); - } else { - baseConsole.groupEnd = () => {}; - } + baseConsole.groupEnd = defineName( + 'groupEnd', + baseConsole.groupEnd + ? (...args) => { + arrayPop(indents); + } + : () => {}, + ); harden(baseConsole); const causalConsole = makeCausalConsole( /** @type {VirtualConsole} */ (baseConsole), @@ -518,14 +525,14 @@ export const filterConsole = (baseConsole, filter, _topic = undefined) => { /** * @param {...any} args */ - const method = (...args) => { + const method = defineName(name, (...args) => { // eslint-disable-next-line @endo/no-polymorphic-call if (severity === undefined || filter.canLog(severity)) { // @ts-ignore // eslint-disable-next-line @endo/no-polymorphic-call baseConsole[name](...args); } - }; + }); return [name, freeze(method)]; }); const filteringConsole = fromEntries(methods);