Skip to content

Commit

Permalink
fix(ses,pass-style,marshal): tolerate platforms prior to AggregateError
Browse files Browse the repository at this point in the history
  • Loading branch information
erights authored and kriskowal committed Feb 22, 2024
1 parent 6a8c4d8 commit 5762dd4
Show file tree
Hide file tree
Showing 17 changed files with 80 additions and 34 deletions.
4 changes: 2 additions & 2 deletions packages/common/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
User-visible changes in `@endo/common`:

# next release
# Next release

- Change to `throwLabeled`
- `throwLabeled` parameterized error construction
- Like the assertion functions/methods that were parameterized by an error
constructor (`makeError`, `assert`, `assert.fail`, `assert.equal`),
`throwLabeled` now also accepts named options `cause` and `errors` in its
Expand Down
2 changes: 1 addition & 1 deletion packages/errors/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
User-visible changes in `@endo/errors`:

# next release
# Next release

- `AggegateError` support
- Assertion functions/methods that were parameterized by an error constructor
Expand Down
2 changes: 1 addition & 1 deletion packages/marshal/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
User-visible changes in `@endo/marshal`:

# next release
# Next release

- Sending and receiving extended errors.
- As of the previous release, `@endo/marshal` tolerates extra error
Expand Down
19 changes: 8 additions & 11 deletions packages/marshal/test/test-marshal-capdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,20 @@ test('unserialize errors', t => {
});

test('unserialize extended errors', t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const { unserialize } = makeTestMarshal();
const uns = body => unserialize({ body, slots: [] });

// TODO cause, errors, and AggregateError will eventually be recognized.
// See https://github.com/endojs/endo/pull/2042

const refErr = uns(
'{"@qclass":"error","message":"msg","name":"ReferenceError","extraProp":"foo","cause":"bar","errors":["zip","zap"]}',
);
t.is(getPrototypeOf(refErr), ReferenceError.prototype); // direct instance of
t.false('extraProp' in refErr);
t.false('cause' in refErr);
t.false('errors' in refErr);
console.log('error with extra prop', refErr);

const aggErr = uns(
'{"@qclass":"error","message":"msg","name":"AggregateError","extraProp":"foo","cause":"bar","errors":["zip","zap"]}',
Expand All @@ -176,7 +176,6 @@ test('unserialize extended errors', t => {
t.false('extraProp' in aggErr);
t.false('cause' in aggErr);
t.is(aggErr.errors.length, 0);
console.log('error with extra prop', aggErr);

const unkErr = uns(
'{"@qclass":"error","message":"msg","name":"UnknownError","extraProp":"foo","cause":"bar","errors":["zip","zap"]}',
Expand All @@ -185,10 +184,12 @@ test('unserialize extended errors', t => {
t.false('extraProp' in unkErr);
t.false('cause' in unkErr);
t.false('errors' in unkErr);
console.log('error with extra prop', unkErr);
});

test('unserialize errors w recognized extensions', t => {
const testIfAggregateError =
typeof AggregateError !== 'undefined' ? test : test.skip;

testIfAggregateError('unserialize errors w recognized extensions', t => {
const { unserialize } = makeTestMarshal();
const uns = body => unserialize({ body, slots: [] });

Expand All @@ -201,7 +202,6 @@ test('unserialize errors w recognized extensions', t => {
t.false('extraProp' in refErr);
t.is(getPrototypeOf(refErr.cause), URIError.prototype);
t.is(getPrototypeOf(refErr.errors[0]), URIError.prototype);
console.log('error with extra prop', refErr);

const aggErr = uns(
`{"@qclass":"error","message":"msg","name":"AggregateError","extraProp":"foo","cause":${errEnc},"errors":[${errEnc}]}`,
Expand All @@ -210,7 +210,6 @@ test('unserialize errors w recognized extensions', t => {
t.false('extraProp' in aggErr);
t.is(getPrototypeOf(aggErr.cause), URIError.prototype);
t.is(getPrototypeOf(aggErr.errors[0]), URIError.prototype);
console.log('error with extra prop', aggErr);

const unkErr = uns(
`{"@qclass":"error","message":"msg","name":"UnknownError","extraProp":"foo","cause":${errEnc},"errors":[${errEnc}]}`,
Expand All @@ -219,8 +218,6 @@ test('unserialize errors w recognized extensions', t => {
t.false('extraProp' in unkErr);
t.is(getPrototypeOf(unkErr.cause), URIError.prototype);
t.is(getPrototypeOf(unkErr.errors[0]), URIError.prototype);

console.log('error with extra prop', unkErr);
});

test('passStyleOf null is "null"', t => {
Expand Down
14 changes: 8 additions & 6 deletions packages/marshal/test/test-marshal-smallcaps.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ test('smallcaps unserialize errors', t => {
});

test('smallcaps unserialize extended errors', t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const { unserialize } = makeTestMarshal();
const uns = body => unserialize({ body, slots: [] });

Expand All @@ -170,7 +174,6 @@ test('smallcaps unserialize extended errors', t => {
t.false('extraProp' in refErr);
t.false('cause' in refErr);
t.false('errors' in refErr);
console.log('error with extra prop', refErr);

const aggErr = uns(
'#{"#error":"msg","name":"AggregateError","extraProp":"foo","cause":"bar","errors":["zip","zap"]}',
Expand All @@ -179,7 +182,6 @@ test('smallcaps unserialize extended errors', t => {
t.false('extraProp' in aggErr);
t.false('cause' in aggErr);
t.is(aggErr.errors.length, 0);
console.log('error with extra prop', aggErr);

const unkErr = uns(
'#{"#error":"msg","name":"UnknownError","extraProp":"foo","cause":"bar","errors":["zip","zap"]}',
Expand All @@ -188,10 +190,13 @@ test('smallcaps unserialize extended errors', t => {
t.false('extraProp' in unkErr);
t.false('cause' in unkErr);
t.false('errors' in unkErr);
console.log('error with extra prop', unkErr);
});

test('smallcaps unserialize errors w recognized extensions', t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const { unserialize } = makeTestMarshal();
const uns = body => unserialize({ body, slots: [] });

Expand All @@ -204,7 +209,6 @@ test('smallcaps unserialize errors w recognized extensions', t => {
t.false('extraProp' in refErr);
t.is(getPrototypeOf(refErr.cause), URIError.prototype);
t.is(getPrototypeOf(refErr.errors[0]), URIError.prototype);
console.log('error with extra prop', refErr);

const aggErr = uns(
`#{"#error":"msg","name":"AggregateError","extraProp":"foo","cause":${errEnc},"errors":[${errEnc}]}`,
Expand All @@ -213,7 +217,6 @@ test('smallcaps unserialize errors w recognized extensions', t => {
t.false('extraProp' in aggErr);
t.is(getPrototypeOf(refErr.cause), URIError.prototype);
t.is(getPrototypeOf(refErr.errors[0]), URIError.prototype);
console.log('error with extra prop', aggErr);

const unkErr = uns(
`#{"#error":"msg","name":"UnknownError","extraProp":"foo","cause":${errEnc},"errors":[${errEnc}]}`,
Expand All @@ -222,7 +225,6 @@ test('smallcaps unserialize errors w recognized extensions', t => {
t.false('extraProp' in unkErr);
t.is(getPrototypeOf(refErr.cause), URIError.prototype);
t.is(getPrototypeOf(refErr.errors[0]), URIError.prototype);
console.log('error with extra prop', unkErr);
});

test('smallcaps mal-formed @qclass', t => {
Expand Down
2 changes: 1 addition & 1 deletion packages/pass-style/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
User-visible changes in `@endo/pass-style`:

# next release
# Next release

- Now supports `AggegateError`, `error.errors`, `error.cause`.
- A `Passable` error can now include an `error.cause` property whose
Expand Down
9 changes: 8 additions & 1 deletion packages/pass-style/src/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ const errorConstructors = new Map(
['URIError', URIError],

// https://github.com/endojs/endo/issues/550
['AggregateError', AggregateError],
// To accommodate platforms prior to AggregateError, we comment out the
// following line and instead conditionally add it to the map below.
// ['AggregateError', AggregateError],
]),
);

if (typeof AggregateError !== 'undefined') {
// Conditional, to accommodate platforms prior to AggregateError
errorConstructors.set('AggregateError', AggregateError);
}

/**
* Because the error constructor returned by this function might be
* `AggregateError`, which has different construction parameters
Expand Down
6 changes: 4 additions & 2 deletions packages/pass-style/src/passStyleOf.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,11 @@ harden(assertPassable);
*
* TODO Deprecate and ultimately delete @agoric/base-zone's `isPassable' in
* favor of this one.
* See https://github.com/endojs/endo/issues/2096
*
* TODO implement an isPassable that does not rely on try/catch.
* This implementation is just a standin until then
* This implementation is just a standin until then.
* See https://github.com/endojs/endo/issues/2096
*
* @param {any} specimen
* @returns {specimen is Passable}
Expand Down Expand Up @@ -299,7 +301,7 @@ export const assertPassableError = err => {
* Return a new passable error that propagates the diagnostic info of the
* original, and is linked to the original as a note.
*
* @param {Error | AggregateError} err
* @param {Error} err
* @returns {Error}
*/
export const toPassableError = err => {
Expand Down
7 changes: 5 additions & 2 deletions packages/pass-style/test/test-extended-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ test('style of extended errors', t => {
const u3 = harden(URIError('u3', { cause: e1 }));
t.is(passStyleOf(u3), 'error');

const a4 = harden(AggregateError([e2, u3], 'a4', { cause: e1 }));
t.is(passStyleOf(a4), 'error');
if (typeof AggregateError !== 'undefined') {
// Conditional, to accommodate platforms prior to AggregateError
const a4 = harden(AggregateError([e2, u3], 'a4', { cause: e1 }));
t.is(passStyleOf(a4), 'error');
}
});
2 changes: 1 addition & 1 deletion packages/patterns/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
User-visible changes in `@endo/patterns`:

# next release
# Next release

- Add `M.tagged(tagPattern, payloadPattern)` for making patterns that match
Passable Tagged objects.
Expand Down
2 changes: 1 addition & 1 deletion packages/ses/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
User-visible changes in SES:

# next release
# Next release

- Now supports `Promise.any`, `AggegateError`, `error.errors`,
and `error.cause`.
Expand Down
5 changes: 4 additions & 1 deletion packages/ses/src/error/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,10 @@ const makeError = (
const messageString = getMessageString(hiddenDetails);
const opts = cause && { cause };
let error;
if (errConstructor === AggregateError) {
if (
typeof AggregateError !== 'undefined' &&
errConstructor === AggregateError
) {
error = AggregateError(errors || [], messageString, opts);
} else {
error = /** @type {ErrorConstructor} */ (errConstructor)(
Expand Down
20 changes: 16 additions & 4 deletions packages/ses/src/permits.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/* eslint-disable no-restricted-globals */
/* eslint max-lines: 0 */

import { arrayPush } from './commons.js';

/**
* @file Exports {@code whitelist}, a recursively defined
* JSON record enumerating all intrinsics and their properties
Expand All @@ -8,8 +12,6 @@
* @author Mark S. Miller
*/

/* eslint max-lines: 0 */

/**
* constantProperties
* non-configurable, non-writable data properties of all global objects.
Expand Down Expand Up @@ -187,17 +189,27 @@ export const uniqueGlobalPropertyNames = {

// All the "subclasses" of Error. These are collectively represented in the
// ECMAScript spec by the meta variable NativeError.
export const NativeErrors = [
/** @type {GenericErrorConstructor[]} */
const NativeErrors = [
EvalError,
RangeError,
ReferenceError,
SyntaxError,
TypeError,
URIError,
// https://github.com/endojs/endo/issues/550
AggregateError,
// Commented out to accommodate platforms prior to AggregateError.
// Instead, conditional push below.
// AggregateError,
];

if (typeof AggregateError !== 'undefined') {
// Conditional, to accommodate platforms prior to AggregateError
arrayPush(NativeErrors, AggregateError);
}

export { NativeErrors };

/**
* <p>Each JSON record enumerates the disposition of the properties on
* some corresponding intrinsic object.
Expand Down
4 changes: 4 additions & 0 deletions packages/ses/test/error/test-aggregate-error-console-demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import '../../index.js';
lockdown();

test('aggregate error console demo', t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const e3 = Error('e3');
const e2 = Error('e2', { cause: e3 });
const u4 = URIError('u4', { cause: e2 });
Expand Down
4 changes: 4 additions & 0 deletions packages/ses/test/error/test-aggregate-error-console.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { throwsAndLogs } from './throws-and-logs.js';
lockdown();

test('aggregate error console', t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const e3 = Error('e3');
const e2 = Error('e2', { cause: e3 });
const u4 = URIError('u4', { cause: e2 });
Expand Down
8 changes: 8 additions & 0 deletions packages/ses/test/error/test-aggregate-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const { getOwnPropertyDescriptor } = Object;
lockdown();

test('aggregate error', t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const e1 = Error('e1');
const e2 = Error('e2', { cause: e1 });
const u3 = URIError('u3', { cause: e1 });
Expand All @@ -28,6 +32,10 @@ test('aggregate error', t => {
});

test('Promise.any aggregate error', async t => {
if (typeof AggregateError === 'undefined') {
t.pass('skip test on platforms prior to AggregateError');
return;
}
const e1 = Error('e1');
const e2 = Error('e2', { cause: e1 });
const u3 = URIError('u3', { cause: e1 });
Expand Down
4 changes: 4 additions & 0 deletions packages/ses/test/error/test-error-cause.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ test('error cause', t => {
enumerable: false,
configurable: true,
});
if (typeof AggregateError === 'undefined') {
t.pass('skip rest of test on platforms prior to AggregateError');
return;
}
const a4 = AggregateError([e2, u3], 'a4', { cause: e1 });
t.is(a4.message, 'a4');
t.is(a4.cause, e1);
Expand Down

0 comments on commit 5762dd4

Please sign in to comment.