Replace boundary structure to preserve embedded value separation

This commit is contained in:
Tony Garnock-Jones 2024-03-12 22:56:01 +01:00
parent 9521fc3dcc
commit 40f5ef4085
2 changed files with 27 additions and 26 deletions

View File

@ -2,22 +2,22 @@
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import * as S from '../gen/sturdy.js'; import * as S from '../gen/sturdy.js';
import { Decoder, DecoderState, Encoder, EncoderState, GenericEmbedded, neverEmbeddedType, EmbeddedType, Value, EmbeddedWriter } from '@preserves/core'; import { Decoder, DecoderState, Encoder, EncoderState, GenericEmbedded, neverEmbeddedType, EmbeddedType, Value, Embedded, EmbeddedWriter } from '@preserves/core';
export const wireRefEmbeddedType: EmbeddedType<S.WireRef> & EmbeddedWriter<S.WireRef> = { export const wireRefEmbeddedType: EmbeddedType<Embedded<S.WireRef>> & EmbeddedWriter<Embedded<S.WireRef>> = {
decode(s: DecoderState): S.WireRef { decode(s: DecoderState): Embedded<S.WireRef> {
return S.asWireRef(new Decoder<any>(s).next()); return new Embedded<S.WireRef>(S.asWireRef(new Decoder<any>(s).next()));
}, },
encode(s: EncoderState, v: S.WireRef): void { encode(s: EncoderState, v: Embedded<S.WireRef>): void {
new Encoder<any>(s, neverEmbeddedType).push(S.fromWireRef(v)); new Encoder<any>(s, neverEmbeddedType).push(S.fromWireRef(v.value));
}, },
fromValue(v: Value<GenericEmbedded>): S.WireRef { fromValue(v: Value<GenericEmbedded>): Embedded<S.WireRef> {
return S.asWireRef(v as Value<S._embedded>); return new Embedded<S.WireRef>(S.asWireRef(v as Value<S._embedded>));
}, },
toValue(v: S.WireRef): Value<GenericEmbedded> { toValue(v: Embedded<S.WireRef>): Value<GenericEmbedded> {
return S.fromWireRef(v) as Value<GenericEmbedded>; return S.fromWireRef(v.value) as Value<GenericEmbedded>;
} }
}; };

View File

@ -2,7 +2,7 @@
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Actor, Assertion, Entity, Facet, Handle, Ref, Turn } from '../runtime/actor.js'; import { Actor, Assertion, Entity, Facet, Handle, Ref, Turn } from '../runtime/actor.js';
import { BytesLike, Decoder, Dictionary, encode, IdentityMap, mapEmbeddeds, stringify, underlying, Value } from '@preserves/core'; import { BytesLike, Decoder, Dictionary, encode, IdentityMap, mapEmbeddeds, Embedded, stringify, underlying, Value } from '@preserves/core';
import * as IO from '../gen/protocol.js'; import * as IO from '../gen/protocol.js';
import { wireRefEmbeddedType } from './protocol.js'; import { wireRefEmbeddedType } from './protocol.js';
import { attenuate } from '../runtime/rewrite.js'; import { attenuate } from '../runtime/rewrite.js';
@ -68,7 +68,7 @@ export class RelayEntity implements Entity {
this.oid = oid; this.oid = oid;
} }
send(m: IO.Event<WireRef>): void { send(m: IO.Event<Embedded<WireRef>>): void {
this.relay.send(this.oid, m); this.relay.send(this.oid, m);
} }
@ -156,7 +156,7 @@ export class Relay {
readonly imported = new Membrane(); readonly imported = new Membrane();
readonly peer: Ref | null; readonly peer: Ref | null;
nextLocalOid: IO.Oid = 0; nextLocalOid: IO.Oid = 0;
pendingTurn: IO.Turn<WireRef> = []; pendingTurn: IO.Turn<Embedded<WireRef>> = [];
debug: boolean; debug: boolean;
trustPeer: boolean; trustPeer: boolean;
@ -180,7 +180,7 @@ export class Relay {
} }
this.peer = (options.initialOid !== void 0) this.peer = (options.initialOid !== void 0)
? this.rewriteRefIn(WireRef.mine(options.initialOid), []) ? this.rewriteRefIn(new Embedded<WireRef>(WireRef.mine(options.initialOid)), [])
: null; : null;
if (options.nextLocalOid !== void 0) { if (options.nextLocalOid !== void 0) {
@ -188,9 +188,9 @@ export class Relay {
} }
} }
register(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<WireRef>; register(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<Embedded<WireRef>>;
register(targetRemoteOid: null, assertion: Assertion, handle: null): Value<WireRef>; register(targetRemoteOid: null, assertion: Assertion, handle: null): Value<Embedded<WireRef>>;
register(targetRemoteOid: IO.Oid | null, assertion: Assertion, handle: Handle | null): Value<WireRef> { register(targetRemoteOid: IO.Oid | null, assertion: Assertion, handle: Handle | null): Value<Embedded<WireRef>> {
const transient = (handle === null); const transient = (handle === null);
const pins: Array<WireSymbol> = []; const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(assertion, r => this.rewriteRefOut(r, transient, pins)); const rewritten = mapEmbeddeds(assertion, r => this.rewriteRefOut(r, transient, pins));
@ -223,18 +223,18 @@ export class Relay {
return e.ref; return e.ref;
} }
rewriteRefOut(r: Ref, transient: boolean, pins: Array<WireSymbol>): WireRef { rewriteRefOut(r: Ref, transient: boolean, pins: Array<WireSymbol>): Embedded<WireRef> {
if (r.target instanceof RelayEntity && r.target.relay === this) { if (r.target instanceof RelayEntity && r.target.relay === this) {
if (r.attenuation === void 0 || r.attenuation.length === 0) { if (r.attenuation === void 0 || r.attenuation.length === 0) {
// No extra conditions on this reference since it was sent to us. // No extra conditions on this reference since it was sent to us.
this.grabImportedOid(r.target.oid, pins); this.grabImportedOid(r.target.oid, pins);
return WireRef.yours({ oid: r.target.oid, attenuation: [] }); return new Embedded<WireRef>(WireRef.yours({ oid: r.target.oid, attenuation: [] }));
} else { } else {
// This reference has been attenuated since it was sent to us. // This reference has been attenuated since it was sent to us.
// Do we trust the peer to enforce such attenuation on our behalf? // Do we trust the peer to enforce such attenuation on our behalf?
if (this.trustPeer) { if (this.trustPeer) {
this.grabImportedOid(r.target.oid, pins); this.grabImportedOid(r.target.oid, pins);
return WireRef.yours({ oid: r.target.oid, attenuation: r.attenuation }); return new Embedded<WireRef>(WireRef.yours({ oid: r.target.oid, attenuation: r.attenuation }));
} else { } else {
// fall through: treat the attenuated ref as a local ref, and re-export it. // fall through: treat the attenuated ref as a local ref, and re-export it.
} }
@ -247,10 +247,11 @@ export class Relay {
return new WireSymbol(this.exported, this.nextLocalOid++, r); return new WireSymbol(this.exported, this.nextLocalOid++, r);
}); });
pins.push(e); pins.push(e);
return WireRef.mine(e.oid); return new Embedded<WireRef>(WireRef.mine(e.oid));
} }
rewriteRefIn(n: WireRef, pins: Array<WireSymbol>): Ref { rewriteRefIn(nw: Embedded<WireRef>, pins: Array<WireSymbol>): Ref {
const n = nw.value;
switch (n._variant) { switch (n._variant) {
case 'yours': { case 'yours': {
const e = this.exported.grab("byOid", n.oid, false, null); const e = this.exported.grab("byOid", n.oid, false, null);
@ -283,7 +284,7 @@ export class Relay {
message(body: Assertion) { message(body: Assertion) {
if (body === FLUSH) { if (body === FLUSH) {
if (this.debug) console.log('OUT', stringify(IO.fromTurn(this.pendingTurn))); if (this.debug) console.log('OUT', stringify(IO.fromTurn(this.pendingTurn)), this.pendingTurn);
this.w(underlying(encode(IO.fromTurn(this.pendingTurn), { this.w(underlying(encode(IO.fromTurn(this.pendingTurn), {
canonical: true, canonical: true,
embeddedEncode: wireRefEmbeddedType, embeddedEncode: wireRefEmbeddedType,
@ -292,7 +293,7 @@ export class Relay {
} }
} }
send(remoteOid: IO.Oid, m: IO.Event<WireRef>): void { send(remoteOid: IO.Oid, m: IO.Event<Embedded<WireRef>>): void {
if (this.pendingTurn.length === 0) { if (this.pendingTurn.length === 0) {
Turn.active.message(this.selfRef, FLUSH); Turn.active.message(this.selfRef, FLUSH);
} }
@ -313,14 +314,14 @@ export class Relay {
}); });
} }
rewriteIn(a: Value<WireRef>): [Assertion, Array<WireSymbol>] rewriteIn(a: Value<Embedded<WireRef>>): [Assertion, Array<WireSymbol>]
{ {
const pins: Array<WireSymbol> = []; const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(a, r => this.rewriteRefIn(r, pins)); const rewritten = mapEmbeddeds(a, r => this.rewriteRefIn(r, pins));
return [rewritten, pins]; return [rewritten, pins];
} }
handle(localOid: IO.Oid, m: IO.Event<WireRef>) { handle(localOid: IO.Oid, m: IO.Event<Embedded<WireRef>>) {
switch (m._variant) { switch (m._variant) {
case 'Assert': { case 'Assert': {
const [a, pins] = this.rewriteIn(m.value.assertion); const [a, pins] = this.rewriteIn(m.value.assertion);