Skip to content

refactor(extension,streams): Abstract envelope handling - #71

Merged
grypez merged 22 commits into
mainfrom
grypez/refactor-envelopes
Sep 17, 2024
Merged

refactor(extension,streams): Abstract envelope handling#71
grypez merged 22 commits into
mainfrom
grypez/refactor-envelopes

Conversation

@grypez

Copy link
Copy Markdown
Member

Closes: #58

Adds makeStreamEnvelopeHandler, which makes a stream envelope handler for handling unknown values.

If the supplied value is a valid envelope with a defined stream envelope handler, the stream envelope handler will return whatever the defined handler returns.

If the stream envelope handler is passed a well-formed stream envelope without a defined handler, an explanation and the envelope will be passed to the supplied stream envelope handler.

If the stream envelope handler encounters an error while parsing the supplied value, it will pass the reason and value to the supplied stream envelope handler.

If no error handler is supplied, the default error handling behavior is to throw.

conststreamEnvelopeHandler=makeStreamEnvelopeHandler({command: handleMessage,capTp: async(content)=>capTp?.dispatch(content),},(reason,value)=>{thrownewError(`[vat IFRAME] ${reason}${stringifyResult(value)}`);},);forawait(constrawMessageofstreams.reader){console.debug('iframe received message',rawMessage);awaitstreamEnvelopeHandler.handle(rawMessage);}

@grypez
grypez requested a review from a team as a code ownerSeptember 14, 2024 08:40
@grypez
grypezforce-pushed the grypez/refactor-envelopes branch from 8085d8f to 20a76b6CompareSeptember 14, 2024 08:41
SMotaal

This comment was marked as outdated.

Comment threadpackages/extension/src/envelope.ts Outdated
Comment threadpackages/extension/src/envelope.ts Outdated
@grypezgrypez changed the title refactor(extension): Abstract envelope handlingrefactor(extension,streams): Abstract envelope handlingSep 15, 2024
@SMotaal
SMotaal dismissed their stale reviewSeptember 15, 2024 18:49

Outdated but with previously requested changes either incorporated or borrowed on in the latest changes.

@SMotaalSMotaal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grypez My review is limited to what was included in my previous review: LGTM

I'm not explicitly approving the PR as a whole as I'd like to give @rekmarks a chance to review and give his final approval.

Comment threadpackages/extension/src/message.ts
Comment threadpackages/extension/src/message.ts
Comment on lines +62 to +67
export type CapTpMessage<Type extends `CTP_${string}` = `CTP_${string}`> = {
type: Type;
epoch: number;
[key: string]: unknown;
};

@SMotaalSMotaalSep 15, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we want to upstream to @endo/captp, maybe bring it up in the next Endo Sync.

Comment threadpackages/extension/src/stream-envelope.ts
Comment threadpackages/streams/documents/make-stream-envelope-kit.md
Comment threadpackages/extension/src/stream-envelope.ts
Comment threadpackages/extension/src/stream-envelope.ts Outdated
makeStreamEnvelopeHandler,
} from './stream-envelope.js';

const defaultCompartment = new Compartment({ URL });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is URL being passed to the Compartment constructor?

@rekmarksrekmarksSep 16, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my decision, but there's no greater intention behind it. I think I was of a mind to use it for demonstration purposes via kernel.evaluate(). Everything Compartment-related in the current vat implementation should be considered a placeholder.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words, this is a placeholder for "some universal endowments go here"?

BTW, IIUC, URL carries no authority, so it shouldn't be needed as an endowment, though it might be desirable to have it in the environment just to avoid having to reimplement it. In this case, it might be sufficient to harden URL, if that is actually possible -- I'm not sure how/if hardening works with exotic objects provided by the host, which I suspect this is, but if harden(URL) doesn't work, putting a hardened wrapper around it should be trivial. As far as I know Agoric hasn't done any work on taming the web APIs, so it's something we might well end up needing to do ourselves (not necessarily a comprehensive taming, but I certainly expect there will be specific things we want to make available to user code).

@rekmarksrekmarks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a final review, but a first pass.

Comment threadpackages/extension/src/stream-envelope.test.ts
Comment threadpackages/extension/src/iframe-manager.ts Outdated
Comment threadpackages/streams/documents/make-stream-envelope-kit.md Outdated
Comment threadpackages/streams/src/enveloper.test.ts Outdated
Comment threadpackages/streams/src/generics.ts
Comment on lines +25 to +39
/* eslint-disable @typescript-eslint/no-unused-expressions */
// eslint-disable-next-line vitest/expect-expect
it('causes a typescript error when supplying typeguard keys not matching the label type', () => {
// @ts-expect-error the bar key is missing
makeStreamEnvelopeKit<typeof labels, ContentMap>({
foo: (value: unknown): value is Foo => true,
});
makeStreamEnvelopeKit<typeof labels, ContentMap>({
foo: (value: unknown): value is Foo => true,
bar: (value: unknown): value is Bar => true,
// @ts-expect-error the qux key is not included in labels
qux: (value: unknown): value is 'qux' => false,
});
});
/* eslint-enable @typescript-eslint/no-unused-expressions */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment goes for all type tests: generally speaking, we haven't bothered with testing our types in this manner. I think the expense is especially difficult to justify for code that is internal to a monorepo, since any bugs or shortcomings of the types will become immediately apparent at development time. Furthermore, in my experience, exhaustive behavioral unit tests are generally sufficient to surface issues with the types.

The other issue with this way of writing type tests is that it's hard on the eyes, and disagreeable to the linter. There are libraries / frameworks that enable it to be done neatly, but adding those would be a bigger decision.

What do you think?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This issue was a challenging typescript exercise for me. The tests helped me validate my assumptions during development. Due to the expense you mentioned I don't advocate them as a required practice, but I do advocate them as an acceptable practice. Given the nuanced type interactions I am more confident in the maintainability of the envelope-kit solution with these type tests in place.

I think the patterns I used here are sufficient and would be helpful if a similar scenario arises, and could serve us well for two more PRs before we consider a dedicated library / framework. The behavioral unit tests cannot check the typing behavior without soothing typescript anyhow, so I collected all the typing assumptions into one test per tested artifact.

To reduce the number of eslint inline configuration comments, I could collect all the type tests into an envelope-kit-types.test.ts and wrap the whole file with the lint exceptions; alternatively we could adopt a convention like envelope-kit.test.types.ts and except these in .eslintrc.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proposed different naming convention: envelope-kit.types.test.ts

@rekmarks

rekmarks commented Sep 17, 2024

Copy link
Copy Markdown
Member

TODO:

  • Move type tests into envelope-kit.types.test.ts, configure exceptions in .eslintrc
  • Move generics.ts to utils/generics.ts
  • Simplify never type assertions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is currently being built to /dist due to its inclusion in /src. The file, however, is useful. I prefer to handle this in the following way:

  • Create a directory /test in the package root directory
  • Add the folder to the included files in tsconfig.jsononly
  • Ensure that the folder is covered by the same ESLint rules as other test files in .eslintrc
  • Import the fixtures from the new location

testEnvelopeHandlers,
);
await expect(
// @ts-expect-error label is intentionally unknown

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

info: We call this practice "intentional destructive testing", and that is also an acceptable explanation string.

@grypez
grypezforce-pushed the grypez/refactor-envelopes branch from f914837 to 6f7c0dcCompareSeptember 17, 2024 19:00
@grypez
grypez enabled auto-merge (squash) September 17, 2024 19:08

@rekmarksrekmarks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@grypez
grypez merged commit b22ba6f into mainSep 17, 2024
@grypez
grypez deleted the grypez/refactor-envelopes branch September 17, 2024 19:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(extension,streams): Abstract envelope handling

5 participants

@grypez@rekmarks@SMotaal@sirtimid@FUDCo