Skip to content

Commit

Permalink
fix(ses): roughly normalize stack strings shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
mhofman committed Oct 7, 2023
1 parent 99d3f4a commit c69c24d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/ses/src/commons.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export const uncurryThis = bind.bind(bind.call); // eslint-disable-line @endo/no

export const objectHasOwnProperty = uncurryThis(objectPrototype.hasOwnProperty);
//
export const arrayEvery = uncurryThis(arrayPrototype.every);
export const arrayFilter = uncurryThis(arrayPrototype.filter);
export const arrayForEach = uncurryThis(arrayPrototype.forEach);
export const arrayIncludes = uncurryThis(arrayPrototype.includes);
Expand Down
66 changes: 65 additions & 1 deletion packages/ses/src/error/tame-error-constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import {
getOwnPropertyDescriptor,
defineProperty,
errorToString,
stringSplit,
stringStartsWith,
stringEndsWith,
arrayEvery,
stringSlice,
stringReplace,
} from '../commons.js';
import { NativeErrors } from '../permits.js';
import { tameV8ErrorConstructor } from './tame-v8-error-constructor.js';
Expand All @@ -19,8 +25,9 @@ const stackDesc = getOwnPropertyDescriptor(FERAL_ERROR.prototype, 'stack');
const stackGetter = stackDesc && stackDesc.get;

// Use concise methods to obtain named functions without constructors.
const defaultGetStackString = {
const basicGetStackString = {
getStackString(error) {
// TODO: format stack properly
if (typeof stackGetter === 'function') {
return apply(stackGetter, error, []);
} else if ('stack' in error) {
Expand All @@ -32,6 +39,63 @@ const defaultGetStackString = {
},
}.getStackString;

const testBasicStackStringShape = () => {
const error = FERAL_ERROR('test message');
error.name = 'TestError';
const stackString = basicGetStackString(error);
const isString = typeof stackString === 'string';
const stackStringLines = stringSplit(isString ? stackString : '', '\n');
const includesErrorDetails =
stringStartsWith(stackStringLines[0], error.name) &&
stringEndsWith(stackStringLines[0], error.message);
const trailingNewLine = stackStringLines[stackStringLines.length - 1] === '';
const stackFrameLinesHaveSpaces = arrayEvery(
stackStringLines,
(line, idx) =>
(includesErrorDetails && idx === 0) ||
(trailingNewLine && idx === stackStringLines.length - 1) ||
stringStartsWith(line, ' '),
);
return {
isString,
includesErrorDetails,
trailingNewLine,
stackFrameLinesHaveSpaces,
};
};

const defaultGetStackString = (() => {
const {
isString,
includesErrorDetails,
trailingNewLine,
stackFrameLinesHaveSpaces,
} = testBasicStackStringShape();
if (
!isString ||
(includesErrorDetails && !trailingNewLine && stackFrameLinesHaveSpaces)
) {
return basicGetStackString;
}
return {
getStackString(error) {
let stackString = basicGetStackString(error);
if (trailingNewLine) {
stackString = stringSlice(stackString, 0, -1);
}
if (!stackFrameLinesHaveSpaces) {
stackString = stringReplace(stackString, /\n/gm, '\n ');
}
if (!includesErrorDetails) {
const details = errorToString(error);
stackString =
details + (stackFrameLinesHaveSpaces ? '\n' : '\n ') + stackString;
}
return stackString;
},
}.getStackString;
})();

export default function tameErrorConstructor(
errorTaming = 'safe',
stackFiltering = 'concise',
Expand Down

0 comments on commit c69c24d

Please sign in to comment.