diff --git a/packages/core/local-protocols/schemas/queuedTasks.prs b/packages/core/local-protocols/schemas/queuedTasks.prs index 7c4877d..94744f7 100644 --- a/packages/core/local-protocols/schemas/queuedTasks.prs +++ b/packages/core/local-protocols/schemas/queuedTasks.prs @@ -5,10 +5,12 @@ ActionDescription = / @spawnActor / @stopActor / @inertCheck -/ -/ +/ +/ / / . +CrossSpacePins = @none #f / @some [#!any ...] . + OptionalAny = / . diff --git a/packages/core/package.json b/packages/core/package.json index 5a21b5b..2add573 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -29,8 +29,8 @@ "types": "lib/index.d.ts", "author": "Tony Garnock-Jones ", "dependencies": { - "@preserves/core": "0.21.1", - "@preserves/schema": "0.22.1", + "@preserves/core": "0.22", + "@preserves/schema": "0.22.3", "salty-crypto": "0.3.1" } } diff --git a/packages/core/src/runtime/actor.ts b/packages/core/src/runtime/actor.ts index 71f5b25..a245893 100644 --- a/packages/core/src/runtime/actor.ts +++ b/packages/core/src/runtime/actor.ts @@ -84,7 +84,7 @@ export function assertionFrom(a: Assertable): Assertion { } } -type OutboundAssertion = { handle: Handle, peer: Ref, established: boolean }; +type OutboundAssertion = { handle: Handle, peer: Ref, crossSpacePins: Ref[] | null, established: boolean }; type OutboundMap = Map; let nextActorId = 0; @@ -205,7 +205,12 @@ export class Facet { _halfLink(other: Facet): void { const h = nextHandle++; - const e = { handle: h, peer: { relay: other, target: new StopOnRetract() }, established: true }; + const e = { + handle: h, + peer: { relay: other, target: new StopOnRetract() }, + crossSpacePins: null, + established: true, + }; this.outbound.set(h, e); } @@ -449,15 +454,23 @@ export class Turn { const assertion = assertionFrom(assertable); const a = runRewrites(ref.attenuation, assertion); if (a !== null) { - const e = { handle: h, peer: ref, established: false }; + const crossSpace = this.activeFacet.actor.space !== ref.relay.actor.space; + const pins = crossSpace ? this.activeFacet.actor.space.extractPins(a) : null; + const e = { handle: h, peer: ref, crossSpacePins: pins, established: false }; this.activeFacet.outbound.set(h, e); this.enqueue(ref.relay, () => { e.established = true; + if (crossSpace) { + ref.relay.actor.space.registerInbound(h, ref, a); + } ref.target.assert?.(a, h); }, () => Q.ActionDescription.assert({ target: ref, + crossSpacePins: (pins === null + ? Q.CrossSpacePins.none() + : Q.CrossSpacePins.some(pins)), handle: h, assertion, })); @@ -486,11 +499,13 @@ export class Turn { () => { if (e.established) { e.established = false; + if (e.crossSpacePins) e.peer.relay.actor.space.deregisterInbound(e.handle); e.peer.target.retract?.(e.handle); } }, () => Q.ActionDescription.retract({ target: e.peer, + crossSpace: e.crossSpacePins !== null, handle: e.handle, })); } diff --git a/packages/core/src/runtime/space.ts b/packages/core/src/runtime/space.ts index ac627ce..dee9a07 100644 --- a/packages/core/src/runtime/space.ts +++ b/packages/core/src/runtime/space.ts @@ -1,8 +1,8 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones -import { IdentitySet } from '@preserves/core'; -import type { Actor, ExitReason } from './actor.js'; +import { IdentityMap, IdentitySet, forEachEmbedded } from '@preserves/core'; +import type { Actor, Assertion, ExitReason, Handle, Ref } from './actor.js'; import type { StructuredTask, TaskDescription } from './task.js'; const LIMIT = 25000; @@ -13,9 +13,12 @@ export enum ActorSpaceState { TERMINATED, } +export type InboundAssertion = { target: Ref, pins: Ref[] }; + export class ActorSpace { actors = new IdentitySet(); state = ActorSpaceState.RUNNING; + inboundAssertions = new IdentityMap(); taskCounter = 0; delayedTasks: Array> = []; @@ -34,6 +37,24 @@ export class ActorSpace { } } + extractPins(assertion: Assertion): Ref[] { + const pins: Ref[] = []; + forEachEmbedded(assertion, (r: Ref) => { + if (r.relay.actor.space === this) { + pins.push(r); + } + }); + return pins; + } + + registerInbound(handle: Handle, target: Ref, assertion: Assertion) { + this.inboundAssertions.set(handle, { target, pins: this.extractPins(assertion) }); + } + + deregisterInbound(handle: Handle) { + this.inboundAssertions.delete(handle); + } + shutdown(reason: Exclude) { if (this.state === ActorSpaceState.TERMINATED) return; this.state = ActorSpaceState.TERMINATED; diff --git a/packages/create/template/package.json b/packages/create/template/package.json index d4bc168..b822931 100644 --- a/packages/create/template/package.json +++ b/packages/create/template/package.json @@ -3,8 +3,8 @@ "version": "0.0.0", "license": "GPL-3.0+", "devDependencies": { - "@preserves/core": "0.21.1", - "@preserves/schema": "0.22.1", + "@preserves/core": "0.22", + "@preserves/schema": "0.22.3", "@syndicate-lang/ts-plugin": "*", "@syndicate-lang/tsc": "*", "rollup": "^2.60", diff --git a/packages/fs/package.json b/packages/fs/package.json index 9fc4975..6f64eb9 100644 --- a/packages/fs/package.json +++ b/packages/fs/package.json @@ -27,8 +27,8 @@ "syndicate-fs": "./bin/syndicate-fs.js" }, "dependencies": { - "@preserves/core": "0.21.1", - "@preserves/schema": "0.22.1", + "@preserves/core": "0.22", + "@preserves/schema": "0.22.3", "@syndicate-lang/core": "^0.15.1", "@syndicate-lang/service": "^0.15.2", "chokidar": "^3.5.3" diff --git a/packages/ws-relay/package.json b/packages/ws-relay/package.json index 7ced3ca..c3a7f2b 100644 --- a/packages/ws-relay/package.json +++ b/packages/ws-relay/package.json @@ -25,7 +25,7 @@ "types": "lib/index.d.ts", "author": "Tony Garnock-Jones ", "dependencies": { - "@preserves/core": "0.21.1", + "@preserves/core": "0.22", "@syndicate-lang/core": "^0.15.1", "salty-crypto": "0.3" }, diff --git a/yarn.lock b/yarn.lock index 421623f..46c937c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1415,17 +1415,17 @@ dependencies: "@octokit/openapi-types" "^12.11.0" -"@preserves/core@0.21.1", "@preserves/core@^0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.21.1.tgz#1e441c9f1e43b7f94543f15f85db6918780f03b5" - integrity sha512-oxgC9YV9PSj2xYfkQdI28RkDIEF2iKvoRZliutRG9Rxc+lvaO93Aj5QepXyPu4U/mJsm6aXPsbXtB84MFUTe4A== +"@preserves/core@0.22", "@preserves/core@^0.22.0": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.22.0.tgz#623a288dd6aa9dc88ce701d03fbfe3bf26720ced" + integrity sha512-7+mjuimRKK/RE8U/82nZ8QR0RLGkVv/R1F6xkWbhr0UJiWVfLByLMm8xWGffDCx9IGhMRRuawXkAuF23hx2EEw== -"@preserves/schema@0.22.1": - version "0.22.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.22.1.tgz#5d9383d90247861ca33f35d255dd0db30f426370" - integrity sha512-uJHRrEdgcvMLGu6jN/W772q5lhZK6eLUR4jmovrTBUfMV6b3Es7D9yVweYoNvHrAXg4HV2kyh1p6KGkTzNsAAw== +"@preserves/schema@0.22.3": + version "0.22.3" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.22.3.tgz#326d2123963b5015b040a2ec1c1c64d1d4838df8" + integrity sha512-sgcs7odGDm+ilmSmwVLMSbXwOpscNmm1CfJcYkucZy3ZzisXHc1uvpQdMAoUTLZep1QU1L0QCQDYD/22KnDQAA== dependencies: - "@preserves/core" "^0.21.1" + "@preserves/core" "^0.22.0" "@types/glob" "^7.1" "@types/minimatch" "^3.0" chalk "^4.1"