Skip to content

Commit

Permalink
fixup! adapt to non-trapping shim
Browse files Browse the repository at this point in the history
  • Loading branch information
erights committed Jan 25, 2025
1 parent be32870 commit 3ceaac9
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 57 deletions.
3 changes: 2 additions & 1 deletion packages/marshal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
"@endo/eventual-send": "workspace:^",
"@endo/nat": "workspace:^",
"@endo/pass-style": "workspace:^",
"@endo/promise-kit": "workspace:^"
"@endo/promise-kit": "workspace:^",
"ses": "workspace:^"
},
"devDependencies": {
"@endo/init": "workspace:^",
Expand Down
13 changes: 7 additions & 6 deletions packages/marshal/src/encodeToCapData.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
// encodes to CapData, a JSON-representable data structure, and leaves it to
// the caller (`marshal.js`) to stringify it.

import { X, Fail, q } from '@endo/errors';
import { freezeOrSuppressTrapping } from 'ses/nonTrappingShimAdapter.js';

import {
passStyleOf,
isErrorLike,
Expand All @@ -17,7 +20,6 @@ import {
nameForPassableSymbol,
passableSymbolForName,
} from '@endo/pass-style';
import { X, Fail, q } from '@endo/errors';

/** @import {Passable, RemotableObject} from '@endo/pass-style' */
/** @import {Encoding, EncodingUnion} from './types.js' */
Expand All @@ -30,8 +32,6 @@ const {
is,
entries,
fromEntries,
// @ts-expect-error TS doesn't see this on ObjectConstructor
suppressTrapping,
} = Object;

/**
Expand Down Expand Up @@ -177,10 +177,11 @@ export const makeEncodeToCapData = (encodeOptions = {}) => {
// We harden the entire capData encoding before we return it.
// `encodeToCapData` requires that its input be Passable, and
// therefore hardened.
// The `suppressTrapping` here is needed anyway, because the `rest` is
// The `freezeOrSuppressTrapping` here is needed anyway, because
// the `rest` is
// freshly constructed by the `...` above, and we're using it
// as imput in another call to `encodeToCapData`.
result.rest = encodeToCapDataRecur(suppressTrapping(rest));
// as input in another call to `encodeToCapData`.
result.rest = encodeToCapDataRecur(freezeOrSuppressTrapping(rest));
}
return result;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/pass-style/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"@endo/env-options": "workspace:^",
"@endo/errors": "workspace:^",
"@endo/eventual-send": "workspace:^",
"@endo/promise-kit": "workspace:^"
"@endo/promise-kit": "workspace:^",
"ses": "workspace:^"
},
"devDependencies": {
"@endo/init": "workspace:^",
Expand Down
7 changes: 3 additions & 4 deletions packages/pass-style/src/passStyle-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@
/** @import {PassStyle} from './types.js' */

import { X, q } from '@endo/errors';
import { isFrozenOrIsNonTrapping } from 'ses/nonTrappingShimAdapter.js';

const { isArray } = Array;
const { prototype: functionPrototype } = Function;
const {
getOwnPropertyDescriptor,
getPrototypeOf,
hasOwnProperty: objectHasOwnProperty,
prototype: objectPrototype,
isFrozen,
// @ts-expect-error TS does not yet have `isNonTrapping` on ObjectConstructor
isNonTrapping,
prototype: objectPrototype,
} = Object;
const { apply } = Reflect;
const { toStringTag: toStringTagSymbol } = Symbol;
Expand Down Expand Up @@ -169,7 +168,7 @@ const makeCheckTagRecord = checkProto => {
CX(check)`A non-object cannot be a tagRecord: ${tagRecord}`)) &&
(isFrozen(tagRecord) ||
(!!check && CX(check)`A tagRecord must be frozen: ${tagRecord}`)) &&
(isNonTrapping(tagRecord) ||
(isFrozenOrIsNonTrapping(tagRecord) ||
(!!check &&
CX(check)`A tagRecord must be non-trapping: ${tagRecord}`)) &&
(!isArray(tagRecord) ||
Expand Down
13 changes: 4 additions & 9 deletions packages/pass-style/src/passStyleOf.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { isPromise } from '@endo/promise-kit';
import { X, Fail, q, annotateError, makeError } from '@endo/errors';
import { isFrozenOrIsNonTrapping } from 'ses/nonTrappingShimAdapter.js';
import { isObject, isTypedArray, PASS_STYLE } from './passStyle-helpers.js';

import { CopyArrayHelper } from './copyArray.js';
Expand Down Expand Up @@ -31,13 +32,7 @@ import { assertPassableString } from './string.js';
/** @typedef {Exclude<PassStyle, PrimitiveStyle | "promise">} HelperPassStyle */

const { ownKeys } = Reflect;
const {
getOwnPropertyDescriptors,
values,
isFrozen,
// @ts-expect-error TS does not yet have `isNonTrapping` on ObjectConstructor
isNonTrapping,
} = Object;
const { isFrozen, getOwnPropertyDescriptors, values } = Object;

/**
* @param {PassStyleHelper[]} passStyleHelpers
Expand Down Expand Up @@ -149,7 +144,7 @@ const makePassStyleOf = passStyleHelpers => {
if (inner === null) {
return 'null';
}
if (!isNonTrapping(inner)) {
if (!isFrozenOrIsNonTrapping(inner)) {
if (!isFrozen(inner)) {
throw assert.fail(
// TypedArrays get special treatment in harden()
Expand Down Expand Up @@ -186,7 +181,7 @@ const makePassStyleOf = passStyleHelpers => {
return 'remotable';
}
case 'function': {
if (!isNonTrapping(inner)) {
if (!isFrozenOrIsNonTrapping(inner)) {
if (!isFrozen(inner)) {
throw Fail`Cannot pass non-frozen objects like ${inner}. Use harden()`;
}
Expand Down
5 changes: 2 additions & 3 deletions packages/pass-style/src/remotable.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="ses"/>

import { Fail, q } from '@endo/errors';
import { isFrozenOrIsNonTrapping } from 'ses/nonTrappingShimAdapter.js';
import {
assertChecker,
canBeMethod,
Expand All @@ -26,8 +27,6 @@ const {
getPrototypeOf,
prototype: objectPrototype,
getOwnPropertyDescriptors,
// @ts-expect-error TS does not yet have `isNonTrapping` on ObjectConstructor
isNonTrapping,
} = Object;

/**
Expand Down Expand Up @@ -155,7 +154,7 @@ const checkRemotable = (val, check) => {
if (confirmedRemotables.has(val)) {
return true;
}
if (!isNonTrapping(val)) {
if (!isFrozenOrIsNonTrapping(val)) {
return (
!!check && CX(check)`cannot serialize non-frozen objects like ${val}`
);
Expand Down
12 changes: 4 additions & 8 deletions packages/pass-style/src/safe-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@

import { isPromise } from '@endo/promise-kit';
import { q } from '@endo/errors';
import { isFrozenOrIsNonTrapping } from 'ses/nonTrappingShimAdapter.js';
import { assertChecker, hasOwnPropertyOf, CX } from './passStyle-helpers.js';

/** @import {Checker} from './types.js' */

const {
getPrototypeOf,
getOwnPropertyDescriptor,
// @ts-expect-error TS does not yet have `isNonTrapping` on ObjectConstructor
isNonTrapping,
} = Object;
const { getPrototypeOf, getOwnPropertyDescriptor } = Object;
const { ownKeys } = Reflect;
const { toStringTag } = Symbol;

Expand Down Expand Up @@ -93,7 +89,7 @@ const checkPromiseOwnKeys = (pr, check) => {
if (
typeof val === 'object' &&
val !== null &&
isNonTrapping(val) &&
isFrozenOrIsNonTrapping(val) &&
getPrototypeOf(val) === Object.prototype
) {
const subKeys = ownKeys(val);
Expand Down Expand Up @@ -137,7 +133,7 @@ const checkPromiseOwnKeys = (pr, check) => {
*/
const checkSafePromise = (pr, check) => {
return (
(isNonTrapping(pr) || CX(check)`${pr} - Must be frozen`) &&
(isFrozenOrIsNonTrapping(pr) || CX(check)`${pr} - Must be frozen`) &&
(isPromise(pr) || CX(check)`${pr} - Must be a promise`) &&
(getPrototypeOf(pr) === Promise.prototype ||
CX(check)`${pr} - Must inherit from Promise.prototype: ${q(
Expand Down
43 changes: 24 additions & 19 deletions packages/pass-style/test/passStyleOf.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
import test from '@endo/ses-ava/prepare-endo.js';

import { q } from '@endo/errors';
import {
hardenOrSuppressTrapping,
freezeOrSuppressTrapping,
} from 'ses/nonTrappingShimAdapter.js';

import { passStyleOf } from '../src/passStyleOf.js';
import { Far, ToFarFunction } from '../src/make-far.js';
Expand All @@ -13,7 +17,7 @@ const harden = /** @type {import('ses').Harden & { isFake?: boolean }} */ (
global.harden
);

const { getPrototypeOf, defineProperty, suppressTrapping } = Object;
const { getPrototypeOf, defineProperty } = Object;
const { ownKeys } = Reflect;

test('passStyleOf basic success cases', t => {
Expand Down Expand Up @@ -113,8 +117,8 @@ test('some passStyleOf rejections', t => {
* For testing purposes, makes a *non-frozen* TagRecord-like object with
* non-enumerable PASS_STYLE and Symbol.toStringTag properties.
* A valid Remotable must inherit from a valid TagRecord.
* - Before stabilize/suppressTrapping, a valid TagRecord must be frozen.
* - After stabilize/suppressTrapping, a valid TagRecord must also be
* - Before stabilize/hardenOrSuppressTrapping, a valid TagRecord must be frozen.
* - After stabilize/hardenOrSuppressTrapping, a valid TagRecord must also be
* stable/non-trapping, for example, because it was hardened.
*
* @param {string} [tag]
Expand Down Expand Up @@ -196,15 +200,15 @@ test('passStyleOf testing remotables', t => {
t.is(passStyleOf(Far('foo', () => 'far function')), 'remotable');

const tagRecord1 = harden(makeTagishRecord('Alleged: manually constructed'));
const farObj1 = suppressTrapping({ __proto__: tagRecord1 });
const farObj1 = hardenOrSuppressTrapping({ __proto__: tagRecord1 });
t.is(passStyleOf(farObj1), 'remotable');

const tagRecord2 = makeTagishRecord('Alleged: tagRecord not hardened');
/**
* Do not freeze `tagRecord2` in order to test that an object with
* a non-frozen __proto__ is not passable.
*/
const farObj2 = suppressTrapping({ __proto__: tagRecord2 });
const farObj2 = freezeOrSuppressTrapping({ __proto__: tagRecord2 });
if (harden.isFake) {
t.is(passStyleOf(farObj2), 'remotable');
} else {
Expand All @@ -215,23 +219,23 @@ test('passStyleOf testing remotables', t => {
}

const tagRecord3 = harden(makeTagishRecord('Alleged: both manually frozen'));
const farObj3 = suppressTrapping({ __proto__: tagRecord3 });
const farObj3 = hardenOrSuppressTrapping({ __proto__: tagRecord3 });
t.is(passStyleOf(farObj3), 'remotable');

const tagRecord4 = harden(makeTagishRecord('Remotable'));
const farObj4 = suppressTrapping({ __proto__: tagRecord4 });
const farObj4 = hardenOrSuppressTrapping({ __proto__: tagRecord4 });
t.is(passStyleOf(farObj4), 'remotable');

const tagRecord5 = harden(makeTagishRecord('Not alleging'));
const farObj5 = suppressTrapping({ __proto__: tagRecord5 });
const farObj5 = hardenOrSuppressTrapping({ __proto__: tagRecord5 });
t.throws(() => passStyleOf(farObj5), {
message:
/For now, iface "Not alleging" must be "Remotable" or begin with "Alleged: " or "DebugName: "; unimplemented/,
});

const tagRecord6 = harden(makeTagishRecord('Alleged: manually constructed'));
const farObjProto6 = suppressTrapping({ __proto__: tagRecord6 });
const farObj6 = suppressTrapping({ __proto__: farObjProto6 });
const farObjProto6 = hardenOrSuppressTrapping({ __proto__: tagRecord6 });
const farObj6 = hardenOrSuppressTrapping({ __proto__: farObjProto6 });
t.is(passStyleOf(farObj6), 'remotable', 'tagRecord grandproto is accepted');

// Our current agoric-sdk plans for far classes are to create a class-like
Expand Down Expand Up @@ -285,7 +289,7 @@ test('passStyleOf testing remotables', t => {
const tagRecordA1 = harden(
makeTagishRecord('Alleged: null-proto tagRecord proto', null),
);
const farObjA1 = suppressTrapping({ __proto__: tagRecordA1 });
const farObjA1 = hardenOrSuppressTrapping({ __proto__: tagRecordA1 });
t.throws(
() => passStyleOf(farObjA1),
{ message: unusualTagRecordProtoMessage },
Expand All @@ -295,8 +299,8 @@ test('passStyleOf testing remotables', t => {
const tagRecordA2 = harden(
makeTagishRecord('Alleged: null-proto tagRecord grandproto', null),
);
const farObjProtoA2 = suppressTrapping({ __proto__: tagRecordA2 });
const farObjA2 = suppressTrapping({ __proto__: farObjProtoA2 });
const farObjProtoA2 = hardenOrSuppressTrapping({ __proto__: tagRecordA2 });
const farObjA2 = hardenOrSuppressTrapping({ __proto__: farObjProtoA2 });
t.throws(
() => passStyleOf(farObjA2),
{ message: unusualTagRecordProtoMessage },
Expand All @@ -310,10 +314,10 @@ test('passStyleOf testing remotables', t => {
const fauxTagRecordB = harden(
makeTagishRecord('Alleged: manually constructed', harden({})),
);
const farObjProtoB = suppressTrapping({
const farObjProtoB = hardenOrSuppressTrapping({
__proto__: fauxTagRecordB,
});
const farObjB = suppressTrapping({ __proto__: farObjProtoB });
const farObjB = hardenOrSuppressTrapping({ __proto__: farObjProtoB });
t.throws(() => passStyleOf(farObjB), {
message:
'cannot serialize Remotables with non-methods like "Symbol(passStyle)" in "[Alleged: manually constructed]"',
Expand All @@ -324,7 +328,7 @@ test('passStyleOf testing remotables', t => {
);
Object.defineProperty(farObjProtoWithExtra, 'extra', { value: () => {} });
harden(farObjProtoWithExtra);
const badFarObjExtraProtoProp = suppressTrapping({
const badFarObjExtraProtoProp = hardenOrSuppressTrapping({
__proto__: farObjProtoWithExtra,
});
t.throws(() => passStyleOf(badFarObjExtraProtoProp), {
Expand Down Expand Up @@ -389,7 +393,8 @@ test('remotables - safety from the gibson042 attack', t => {
* explicitly make this non-trapping, which we cannot yet express.
* @see https://github.com/endojs/endo/blob/master/packages/ses/docs/preparing-for-stabilize.md
*/
const makeInput = () => suppressTrapping({ __proto__: mercurialProto });
const makeInput = () =>
freezeOrSuppressTrapping({ __proto__: mercurialProto });
const input1 = makeInput();
const input2 = makeInput();

Expand Down Expand Up @@ -450,12 +455,12 @@ test('Allow toStringTag overrides', t => {
t.is(`${alice}`, '[object DebugName: Allison]');
t.is(`${q(alice)}`, '"[DebugName: Allison]"');

const carol = suppressTrapping({ __proto__: alice });
const carol = hardenOrSuppressTrapping({ __proto__: alice });
t.is(passStyleOf(carol), 'remotable');
t.is(`${carol}`, '[object DebugName: Allison]');
t.is(`${q(carol)}`, '"[DebugName: Allison]"');

const bob = suppressTrapping({
const bob = hardenOrSuppressTrapping({
__proto__: carol,
[Symbol.toStringTag]: 'DebugName: Robert',
});
Expand Down
24 changes: 24 additions & 0 deletions packages/ses/nonTrappingShimAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
isFrozen,
isNonTrapping as optIsNonTrapping,
freeze,
suppressTrapping as optSuppressTrapping,
} from './src/commons.js';

/**
* Local alias of `isFrozen` to eventually be switched to whatever tests
* the non-trapping integrity trait.
*/
export const isFrozenOrIsNonTrapping = optIsNonTrapping || isFrozen;

/**
* Local alias of `harden` to eventually be switched to whatever applies
* the suppress-trapping integrity trait.
*/
export const hardenOrSuppressTrapping = optSuppressTrapping || harden;

/**
* Local alias of `freeze` to eventually be switched to whatever applies
* the suppress-trapping integrity trait.
*/
export const freezeOrSuppressTrapping = optSuppressTrapping || freeze;
3 changes: 2 additions & 1 deletion packages/ses/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"default": "./compartment-shim.js"
},
"./console-shim.js": "./console-shim.js",
"./ses/nonTrappingShimAdapter.js": "./ses/nonTrappingShimAdapter.js",
"./package.json": "./package.json"
},
"scripts": {
Expand All @@ -86,7 +87,7 @@
},
"dependencies": {
"@endo/env-options": "workspace:^",
"@endo/non-trapping-shim": "^0.1.0"
"@endo/non-trapping-shim": "workspace:^"
},
"devDependencies": {
"@endo/compartment-mapper": "workspace:^",
Expand Down
2 changes: 2 additions & 0 deletions packages/ses/src/commons.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ export const {
preventExtensions: reflectPreventExtensions,
set: reflectSet,
// https://github.com/endojs/endo/pull/2673
// @ts-expect-error TS does not yet have this on Reflect.
isNonTrapping: reflectIsNonTrapping,
// @ts-expect-error TS does not yet have this on Reflect.
suppressTrapping: reflectSuppressTrapping,
} = Reflect;

Expand Down
Loading

0 comments on commit 3ceaac9

Please sign in to comment.