Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/pass-style/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ User-visible changes in `@endo/pass-style`:

# Next release

- deprecates `assertChecker`. Use `Fail` in the confirm/reject pattern instead, as supported by `@endo/errors/rejector.js`.
- Deprecates `assertChecker`. Use `Fail` in the confirm/reject pattern instead,
as supported by `@endo/errors/rejector.js`.
- Enables `passStyleOf` to make errors passable as a side-effect when SES locks
down with `hardenTaming` set to `unsafe`, which impacts errors on V8 starting
with Node.js 21, and similar engines, that own a `stack` getter and setter
that would otherwise be repaired as a side-effect of `harden`.
- Updates `CopyArray<T>` to be a `ReadonlyArray<Passable>`. We know dynamically
that the CopyArray is hardened, so this typing statically reveals where
mutation is attempted. Use `Passable[]` if you want to have a mutable array
that contains only passable values.

# 1.6.3 (2025-07-11)

Expand Down
15 changes: 10 additions & 5 deletions packages/pass-style/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ export type Container<PC extends PassableCap, E extends Error> =
| CopyArrayInterface<PC, E>
| CopyRecordInterface<PC, E>
| CopyTaggedInterface<PC, E>;
interface CopyArrayInterface<PC extends PassableCap, E extends Error>
export interface CopyArrayInterface<PC extends PassableCap, E extends Error>
extends CopyArray<Passable<PC, E>> {}
interface CopyRecordInterface<PC extends PassableCap, E extends Error>
export interface CopyRecordInterface<PC extends PassableCap, E extends Error>
extends CopyRecord<Passable<PC, E>> {}
interface CopyTaggedInterface<PC extends PassableCap, E extends Error>
export interface CopyTaggedInterface<PC extends PassableCap, E extends Error>
extends CopyTagged<string, Passable<PC, E>> {}

export type PassStyleOf = {
Expand All @@ -134,7 +134,7 @@ export type PassStyleOf = {
(p: Promise<any>): 'promise';
(p: Error): 'error';
(p: CopyTagged): 'tagged';
(p: any[]): 'copyArray';
(p: readonly any[]): 'copyArray';
(p: Iterable<any>): 'remotable';
(p: Iterator<any, any, undefined>): 'remotable';
<T extends PassStyled<PassStyleMarker, any>>(p: T): ExtractStyle<T>;
Expand Down Expand Up @@ -199,10 +199,15 @@ export type PassableCap =
| RemotableObject
| RemotableBrand<any, any>;

/**
* Types you would get from Awaited<PassableCap>
*/
export type AwaitedPassableCap = RemotableObject | RemotableBrand<any, any>;

/**
* A Passable sequence of Passable values.
*/
export type CopyArray<T extends Passable = any> = Array<T>;
export type CopyArray<T extends Passable = any> = ReadonlyArray<T>;

/**
* A hardened immutable ArrayBuffer.
Expand Down
28 changes: 28 additions & 0 deletions packages/pass-style/src/types.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ expectType<PassStyle>(passStyleOf(someUnknown));

const expectPassable = (val: Passable) => {};

() => {
const arr = ['hello'] as string[];
expectPassable(arr);
arr.push('world');
const slice = arr.slice();
expectPassable(slice);
arr.shift();
slice.shift();
};

() => {
const roArr = ['hello'] as Readonly<string[]>;
expectPassable(roArr);
// @ts-expect-error immutable
roArr.push('world');
const roSlice = roArr.slice();
expectPassable(roSlice);
// @ts-expect-error immutable
roArr.shift();
roSlice.shift();
};

const fn = () => {};

expectPassable(1);
Expand All @@ -44,6 +66,12 @@ expectPassable(fn());

expectPassable({});
expectPassable({ a: {} });
expectPassable({ a: { b: {} } });
expectPassable(['car', 'cdr']);
expectPassable(['car', 'cdr'] as string[]);
expectPassable([['a'], ['b']] as const);
expectPassable(['car', 'cdr'] as Readonly<string[]>);
expectPassable(['car', 'cdr'] as Readonly<[string, string]>);
// @ts-expect-error not passable
expectPassable(fn);
// FIXME promise for a non-Passable is not Passable
Expand Down