Embed a string directly into error details without wrapping punctuation.
To avoid injection attacks that exploit quoting confusion, this must NEVER
be used with data that is possibly attacker-controlled.
As a further safeguard, we fall back to quoting any input that is not a
string of sufficiently word-like parts separated by isolated spaces (rather
than throwing an exception, which could hide the original problem for which
explanatory details are being constructed---i.e., assert.details`...`
should never be the source of a new exception, nor should an attempt to
render its output, although we could instead decide to handle the latter
by inline replacement similar to that of bestEffortStringify
for producing
rendered messages like (an object) was tagged "[Unsafe bare string]"
).
What to declassify
Optional
spaces: string | numberUse the details
function as a template literal tag to create
informative error messages. The assertion functions take such messages
as optional arguments:
assert(sky.isBlue(), details`${sky.color} should be "blue"`);
or following the normal convention to locally rename details
to X
and quote
to q
like const { details: X, quote: q } = assert;
:
assert(sky.isBlue(), X`${sky.color} should be "blue"`);
However, note that in most cases it is preferable to instead use the Fail
template literal tag (which has the same input signature as details
but automatically creates and throws an error):
sky.isBlue() || Fail`${sky.color} should be "blue"`;
The details template tag returns a DetailsToken
object that can print
itself with the formatted message in two ways.
It will report full details to the console, but
mask embedded substitution values with their typeof information in the thrown error
to prevent revealing secrets up the exceptional path. In the example
above, the thrown error may reveal only that sky.color
is a string,
whereas the same diagnostic printed to the console reveals that the
sky was green. This masking can be disabled for an individual substitution value
using quote
.
The raw
property of an input template array is ignored, so a simple
array of strings may be provided directly.
Rest
...args: anyAka the makeError
function as imported from @endo/errors
Recording unredacted details for the console.
Optional
details: DetailsThe details of what was asserted
Optional
errConstructor: GenericErrorConstructorAn optional alternate error constructor to use
Optional
options: AssertMakeErrorOptionsAka the annotateError
function as imported from @endo/errors
Annotate an error with details, potentially to be used by an
augmented console such as the causal console of console.js
, to
provide extra information associated with logged errors.
To "declassify" and quote a substitution value used in a
details`...`
template literal, enclose that substitution expression
in a call to quote
. This makes the value appear quoted
(as if with JSON.stringify
) in the message of the thrown error. The
payload itself is still passed unquoted to the console as it would be
without quote
.
For example, the following will reveal the expected sky color, but not the actual incorrect sky color, in the thrown error's message:
sky.color === expectedColor || Fail`${sky.color} should be ${quote(expectedColor)}`;
The normal convention is to locally rename details
to X
and quote
to q
like const { details: X, quote: q } = assert;
, so the above example would then be
sky.color === expectedColor || Fail`${sky.color} should be ${q(expectedColor)}`;
What to declassify
Optional
spaces: string | number
Use the
Fail
function as a template literal tag to efficiently create and throw adetails
-style error only when a condition is not satisfied.This avoids the overhead of creating usually-unnecessary errors like
while improving readability over alternatives like
However, due to current weakness in TypeScript, static reasoning is less powerful with the
||
patterns than with anassert
call. Until/unless https://github.com/microsoft/TypeScript/issues/51426 is fixed, for||
-style assertions where this loss of static reasoning is a problem, instead express the assertion asor, if needed,