From ed605718e52413a63eb3f3f898dd3731a261045a Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Fri, 1 Dec 2023 20:53:18 +0100 Subject: [PATCH] Global Dataspace and ActorSpace available --- packages/compiler/src/compiler/codegen.ts | 2 +- packages/core/package.json | 1 + packages/core/src/runtime/actor.ts | 15 +++++------ packages/core/src/runtime/dataspace.ts | 32 ++++++++++++++++++++++- packages/html/src/index.ts | 4 +-- packages/timer/src/index.ts | 4 +-- packages/ws-relay/src/index.ts | 3 ++- yarn.lock | 2 +- 8 files changed, 46 insertions(+), 17 deletions(-) diff --git a/packages/compiler/src/compiler/codegen.ts b/packages/compiler/src/compiler/codegen.ts index 39669ed..202d43f 100644 --- a/packages/compiler/src/compiler/codegen.ts +++ b/packages/compiler/src/compiler/codegen.ts @@ -182,7 +182,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} : ``; */ const n = spawn.name === void 0 ? '' : t` __SYNDICATE__.Turn.activeFacet.actor.name = ${walk(spawn.name)};`; - return t`__SYNDICATE__.Turn.active._spawn${spawn.linkedToken ? 'Link': ''}(() => {${n} ${inject} ${walk(spawn.body)} });`; + return t`__SYNDICATE__.Dataspace._spawn${spawn.linkedToken ? 'Link': ''}(() => {${n} ${inject} ${walk(spawn.body)} });`; } x(ctx.parser.spawn, expandSpawn); diff --git a/packages/core/package.json b/packages/core/package.json index f65e5d4..75f1c3e 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -29,6 +29,7 @@ "types": "lib/index.d.ts", "author": "Tony Garnock-Jones ", "devDependencies": { + "@preserves/core": "0.992", "@preserves/schema-cli": "0.992" }, "peerDependencies": { diff --git a/packages/core/src/runtime/actor.ts b/packages/core/src/runtime/actor.ts index 1e2a018..91a2a5b 100644 --- a/packages/core/src/runtime/actor.ts +++ b/packages/core/src/runtime/actor.ts @@ -8,6 +8,7 @@ import { ActorSpace } from './space.js'; import { ActionDescription, StructuredTask, TaskAction } from './task.js'; import { randomId } from './randomid.js'; import * as Q from '../gen/queuedTasks.js'; +import { Dataspace } from './dataspace.js'; export type AnyValue = Value; @@ -101,15 +102,11 @@ export class Actor { exitReason: ExitReason = null; readonly exitHooks: Array = []; - static boot(bootProc: LocalAction, space: ActorSpace, initialAssertions?: OutboundMap): Actor; - static boot(bootProc: LocalAction, initialAssertions?: OutboundMap): Actor; - static boot(bootProc: LocalAction, spaceOrInitialAssertions?: ActorSpace | OutboundMap, initialAssertions0?: OutboundMap): Actor { - const space: ActorSpace = (spaceOrInitialAssertions && !Map.isMap(spaceOrInitialAssertions)) - ? spaceOrInitialAssertions - : new ActorSpace(); - const initialAssertions: OutboundMap | undefined = (spaceOrInitialAssertions && Map.isMap(spaceOrInitialAssertions)) - ? spaceOrInitialAssertions - : (spaceOrInitialAssertions ? initialAssertions0 : void 0); + static boot( + bootProc: LocalAction, + initialAssertions: OutboundMap = new Map(), + space = new ActorSpace(), + ): Actor { const newActor = new Actor(space, initialAssertions); newActor._boot(bootProc); return newActor; diff --git a/packages/core/src/runtime/dataspace.ts b/packages/core/src/runtime/dataspace.ts index 9521e1f..f0c9556 100644 --- a/packages/core/src/runtime/dataspace.ts +++ b/packages/core/src/runtime/dataspace.ts @@ -3,7 +3,7 @@ import { IdentityMap, KeyedDictionary, stringify } from '@preserves/core'; import { Index, IndexObserver } from './skeleton.js'; -import { Actor, AnyValue, Assertion, Entity, Facet, Handle, LocalAction, Ref, Turn } from './actor.js'; +import { Actor, AnyValue, Assertion, DetailedAction, Entity, Facet, Handle, LocalAction, Ref, Turn } from './actor.js'; import { Observe, toObserve } from '../gen/dataspace.js'; import * as P from '../gen/dataspacePatterns.js'; @@ -46,6 +46,36 @@ export class DataspaceObserver implements IndexObserver { } export class Dataspace implements Partial { + private static _global: Ref | undefined = void 0; + + static get global(): Ref { + if (Dataspace._global === void 0) { + Dataspace.boot(ds => { + // Cast to any because `global` is otherwise readonly (!) + Dataspace._global = ds; + }); + } + return Dataspace._global!; + } + + // Alias for syndicatec code generator to use, plus hook for fallback use outside a Turn + static _spawnLink(bootProc: LocalAction | DetailedAction): Actor | null { + if (Turn.active) { + return Turn.active._spawnLink(bootProc); + } else { + throw new Error("Cannot spawnLink outside an active Turn"); + } + } + + // Alias for syndicatec code generator to use, plus hook for fallback use outside a Turn + static _spawn(bootProc: LocalAction | DetailedAction): Actor { + if (Turn.active) { + return Turn.active._spawn(bootProc); + } else { + return Actor.boot(bootProc, void 0, Dataspace.global.relay.actor.space); + } + } + readonly options: DataspaceOptions; readonly index = new Index(); readonly handleMap = new IdentityMap(); diff --git a/packages/html/src/index.ts b/packages/html/src/index.ts index ab29004..954f680 100644 --- a/packages/html/src/index.ts +++ b/packages/html/src/index.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones -import { randomId, Observe, FlexMap, embed, Embedded, Ref, Turn, AnyValue } from "@syndicate-lang/core"; +import { randomId, Observe, FlexMap, embed, Embedded, Ref, Turn, AnyValue, Dataspace } from "@syndicate-lang/core"; import { QuasiValue as Q } from "@syndicate-lang/core"; import * as P from "./protocol"; @@ -11,7 +11,7 @@ export type UIFragmentRecord = ReturnType; import { HtmlFragments } from "./html"; export * from "./html"; -export function boot(ds: Ref) { +export function boot(ds = Dataspace.global) { spawnGlobalEventFactory(ds); spawnWindowEventFactory(ds); spawnUIFragmentFactory(ds); diff --git a/packages/timer/src/index.ts b/packages/timer/src/index.ts index 87921be..36ea35e 100644 --- a/packages/timer/src/index.ts +++ b/packages/timer/src/index.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones -import { preserves, DoubleFloat, Observe, floatValue, Turn, Ref, Schemas } from "@syndicate-lang/core"; +import { preserves, DoubleFloat, Observe, floatValue, Turn, Ref, Schemas, Dataspace } from "@syndicate-lang/core"; import { QuasiValue as Q } from "@syndicate-lang/core"; export message type PeriodicTick(interval: DoubleFloat); @@ -20,7 +20,7 @@ export function sleep(ds: Ref, seconds: number, cb: () => void): void { } } -export function boot(ds: Ref) { +export function boot(ds = Dataspace.global) { spawn named 'timer/PeriodicTick' { at ds { during Observe({ diff --git a/packages/ws-relay/src/index.ts b/packages/ws-relay/src/index.ts index 1c17357..95b6b3f 100644 --- a/packages/ws-relay/src/index.ts +++ b/packages/ws-relay/src/index.ts @@ -4,6 +4,7 @@ import { Assertion, Bytes, + Dataspace, Embedded, IdentitySet, Observe, @@ -31,7 +32,7 @@ type TransportState = { peer: Ref, }; -export function boot(ds: Ref, debug: boolean = false, WebSocketConstructor?: typeof WebSocket) { +export function boot(ds = Dataspace.global, debug: boolean = false, WebSocketConstructor?: typeof WebSocket) { spawn named 'transportConnector' { at ds { during Observe({ "pattern": :pattern G.TransportConnection({ diff --git a/yarn.lock b/yarn.lock index 1ddd8d2..d0f186b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1403,7 +1403,7 @@ dependencies: "@octokit/openapi-types" "^12.11.0" -"@preserves/core@*", "@preserves/core@^0.992.3": +"@preserves/core@*", "@preserves/core@0.992", "@preserves/core@^0.992.3": version "0.992.3" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.992.3.tgz#776a43db71c95cc4d1c276ebe85aef39587a6f4c" integrity sha512-thDNEIAvD1j4OZqAItXEdKSR/wklKp/lCY2Lxdmj8oLRM82jaTzvlvkQwUIK08zcV3QVBaIed/UeG4J1W4Jlrw==