feat(ocapn): Minimum viable OCapN#2781
Conversation
c7275c8 to
8cc0aec
Compare
fe3ebc4 to
41f429e
Compare
|
When attempting to use OCapN reifies ByteArrays as Uint8Arrays, but @erights i think you're working on support for something like an |
Doh! I think I know what the problem is. Will investigate. Attn @kriskowal
https://github.com/endojs/endo/blob/master/packages/immutable-arraybuffer/shim.js I think one of #1538 or #2414 is redundant and should be closed in favor of the other one. I plan to look at these soon anyway, doing maintenance and bringing them up to date. Would love any feedback! |
Especially since the proposal has reached stage 2.7 with no significant impediments to stage 3.0 (just further work on the test262 tests). We agreed at a recent Endo meeting that this was close enough for these dependent PRs to move ahead towards merging into endo master. (IIRC, you were there.) |
14236e1 to
db7bd65
Compare
50ad13e to
0708a36
Compare
933f2c4 to
e1b3226
Compare
kriskowal
left a comment
There was a problem hiding this comment.
Looks like progress to me. I’m recommending that we capture issues for all the TODOs especially debts accrued by deferring alignment with @endo/pass-style.
Given that this doesn’t line up with the past, I would like it to line up with our best understanding of the anticipated future, so
- please use ArrayBuffer for the representation of ByteArray (not Uint8Array) and also
- use the name and representation of Symbol instead of Selector. I’ve made a note about what we want to do with
methodNameForSymbol.
I am not sure what we’re going to do about your OCapNFar functions to reconcile with Far, but we must do something in pass-style and not bind that solution to OCapN. I don’t know what that solution is yet. But, makeExo and Far need to be sufficiently generic that they produce objects that work equally well with both CapTP and OCapN. I would be fine, for now, if you simply renamed your routine Far and moved it into your pass-style utility.
| const otherDir = slot[1] === '+' ? '-' : '+'; | ||
| const revslot = `${slot[0]}${otherDir}${slot.slice(2)}`; | ||
| return revslot; |
There was a problem hiding this comment.
I have a fantasy where this function is simply:
const [table, pos] = slot;
return [table, -pos];| export const getSelectorName = selector => { | ||
| if (selector[PASS_STYLE] !== 'selector') { | ||
| throw Error(`Selector expected, got ${typeof selector}`); | ||
| } | ||
| return selector[Symbol.toStringTag]; | ||
| }; |
There was a problem hiding this comment.
I think we’re converging on (attn @erights). For context, the notion is to merge this OCapN implementation before pass-style is ready and to leave extensive notes with linked issues. The issue here is that this module will eventually be replaced with @endo/pass-style and so needs to converge on the same end state.
| export const getSelectorName = selector => { | |
| if (selector[PASS_STYLE] !== 'selector') { | |
| throw Error(`Selector expected, got ${typeof selector}`); | |
| } | |
| return selector[Symbol.toStringTag]; | |
| }; | |
| export const methodNameForSymbol = symbol => { | |
| if (symbol[PASS_STYLE] !== 'symbol') { | |
| throw Error(`Selector expected, got ${typeof symbol}`); | |
| } | |
| tag = symbol[Symbol.toStringTag]; | |
| if (tag === '@@asyncIterator') { | |
| return Symbol.asyncIterator; | |
| } else if (tag === 'then') { | |
| return Symbol.for('then'); // import { THEN } from "@endo/pass-style"; | |
| } else if (tag === 'constructor') { | |
| return Symbol.for('constructor'); // import { CONSTRUCTOR } from "@endo/pass-style"; | |
| } else { | |
| return tag; | |
| } | |
| }; |
There was a problem hiding this comment.
I might punt adding special behavior for asyncIterator etc until I understand it better. also relates to how we handle OCapNFar.
| import { PASS_STYLE } from '@endo/pass-style'; | ||
|
|
||
| const { freeze, prototype: ObjectPrototype, create } = Object; | ||
|
|
There was a problem hiding this comment.
Should capture a makeByteArray or byteArrayFrom here so we have a single place to change when lining up the representations.
There was a problem hiding this comment.
i tried implementing this and it started snaking out all over the code base. unsure what should be a ByteArray and what is fine being eg a Uint8Array. I'd rather revisit this with the ImmutableArrayBuffer shim.
There was a problem hiding this comment.
Let’s think about what it will take to make ocapn usable in a shim-free environment. @erights
There was a problem hiding this comment.
Let’s think about what it will take to make ocapn usable in a shim-free environment.
IMO, too hard, unless you want to wait for native implementations of the Immutable ArrayBuffer proposal. passStyleOf should only succeed on passables, which must therefore be hardened. The proposal would make either hardened Immutable ArrayBuffers or hardened frozen Uint8Arrays plausible choices for binding to ocapn ByteArray.
However, IMO, waiting for native implementations of Immutable ArrayBuffer would take too long. So the only reasonable choice IMO is to use the shim. The Shim's emulated Immutable ArrayBuffers can be made passable. But the shim cannot make Uint8Arrays passable, and has no reasonable way to emulate a frozen Uint8Array. So, for ocapn to proceed prior to native implementations, we gotta use the shim and bind Immutable ArrayBuffers to ocapn ByteArrays.
There was a problem hiding this comment.
This might be model.js or passable.js.
There was a problem hiding this comment.
this is used for testing and debugging. this is an otherwise unused direct reification of syrup to javascript. it is used by the ocapn client to log extra error info when it fails to parse an ocapn message.
There was a problem hiding this comment.
so i left it alone for now, but yeah "naming things"
…ass-style selectors
24ebd47 to
f481aa8
Compare
59a0d27 to
88f56ff
Compare
88f56ff to
770fa30
Compare
kriskowal
left a comment
There was a problem hiding this comment.
I’ve made some notes. This meets my bar for a package that is not yet published and based on a still-wet specification and I’m eager to move forward quickly.
| const makeSlotForValue = val => { | ||
| /** @type {CapTPSlot} */ | ||
| let slot; | ||
| if (isPromise(val)) { |
There was a problem hiding this comment.
passStyleOf(valu) === 'promise' will be more resilient to future changes.
| } | ||
| seen.clear(); | ||
| }, | ||
| abort() { |
There was a problem hiding this comment.
Maybe just clear for this name.
| swissnumTable = new Map(), | ||
| giftTable = new Map(), |
There was a problem hiding this comment.
Given that the caller can retain these options, is there an expectation that they can update them or observe changes to them after calling makeClient? If there is no such expectation, we should capture a snapshot and discard the option. If there is such an expectation, I’m weary about the semantics and the observability story.
There was a problem hiding this comment.
is there an expectation that they can update them or observe changes to them after calling makeClient
no. i've introduced them for tests, but they could also be part of a persistence system
we should capture a snapshot and discard the option.
seems fine. though we may inspect giftTable in tests
| return `${location.transport}:${location.address}`; | ||
| }; | ||
|
|
||
| const swissnumDecoder = new TextDecoder('ascii', { fatal: true }); |
There was a problem hiding this comment.
I don’t believe that this usage is portable. Consider trivially hand-rolling this routine. I think it’s just something like String.fromCode(...array) as long as you assert that the values of the array are covered by the 0x7f mask.
| import { PASS_STYLE } from '@endo/pass-style'; | ||
|
|
||
| const { freeze, prototype: ObjectPrototype, create } = Object; | ||
|
|
There was a problem hiding this comment.
Let’s think about what it will take to make ocapn usable in a shim-free environment. @erights
| swissnumTable: makeDefaultSwissnumTable && makeDefaultSwissnumTable(), | ||
| }); | ||
| const tcpNetlayer = await makeTcpNetLayer({ client }); | ||
| client.registerNetlayer(tcpNetlayer); |
There was a problem hiding this comment.
I’m sure you’ve got an eye on how this integrates with the pet dæmon. We can add and remove netlayers at runtime? We probably ought to synchronously disconnect all living sessions for a netlayer when it’s unregistered.
|
replaced by #2962 |
This PR is intended to land a work-in-progress implementation of the client, and is not ready to be published.
The implementation is a single vat single process (no comms vat).
tcp-testing-onlynetlayer (no tor netlayer yet)This does not yet implement GC messages.
this was mostly built against this test suite https://github.com/ocapn/ocapn-test-suite
which lags behind the spec a bit. I expect dramatic spec changes to come, so I don't mind being behind spec at this point.
There is some implementation weirdness around use of
pass-styledue to a need for anImmutableArrayBuffer. This implementation currently still uses mutableUint8Arraysand thus some homespunpassStyleOfchecks. The intention is to replace these with exclusively realpass-stylebefore publishing.rebased on #2772