diff --git a/packages/core/examples/box-and-client.ts b/packages/core/examples/box-and-client.ts
index 5ea219b..53e65c5 100755
--- a/packages/core/examples/box-and-client.ts
+++ b/packages/core/examples/box-and-client.ts
@@ -17,7 +17,7 @@
// along with this program. If not, see .
//---------------------------------------------------------------------------
-import { bootModule, Skeleton, Record, Discard, Capture, Observe, Facet, DataflowObservableObject } from '..';
+import { bootModule, Skeleton, Record, Discard, Capture, Observe, Facet } from '..';
const __ = Discard._instance;
const _$ = Capture(__);
@@ -28,67 +28,66 @@ const N = 100000;
console.time('box-and-client-' + N.toString());
-function boot(thisFacet: Facet) {
- thisFacet.spawn('box', function (this: DataflowObservableObject & {
- value: number;
- }, thisFacet: Facet) {
- thisFacet.declareField(this, 'value', 0);
- thisFacet.addEndpoint(() => {
- // console.log('recomputing published BoxState', this.value);
- return { assertion: BoxState(this.value), analysis: null };
- });
- thisFacet.addDataflow(() => {
- // console.log('dataflow saw new value', this.value);
- if (this.value === N) {
- thisFacet.stop(() => {
- console.log('terminated box root facet');
+function boot(thisFacet: Facet<{}>) {
+ thisFacet.spawn<{ value: number }>('box', function (thisFacet) {
+ thisFacet.declareField(this, 'value', 0);
+ thisFacet.addEndpoint(function () {
+ // console.log('recomputing published BoxState', this.value);
+ return { assertion: BoxState(this.value), analysis: null };
+ });
+ thisFacet.addDataflow(function () {
+ // console.log('dataflow saw new value', this.value);
+ if (this.value === N) {
+ thisFacet.stop(function () {
+ console.log('terminated box root facet');
+ });
+ }
+ });
+ thisFacet.addEndpoint(function () {
+ let analysis = Skeleton.analyzeAssertion(SetBox(_$));
+ analysis.callback = thisFacet.wrap(function (thisFacet, evt, [v]) {
+ if (evt === Skeleton.EventType.MESSAGE) {
+ if (typeof v !== 'number') return;
+ thisFacet.scheduleScript(function () {
+ this.value = v;
+ // console.log('box updated value', v);
+ });
+ }
+ });
+ return { assertion: Observe(SetBox(_$)), analysis };
});
- }
});
- thisFacet.addEndpoint(() => {
- let analysis = Skeleton.analyzeAssertion(SetBox(_$));
- analysis.callback = thisFacet.wrap((thisFacet, evt, [v]) => {
- if (evt === Skeleton.EventType.MESSAGE) {
- if (typeof v !== 'number') return;
- thisFacet.scheduleScript(() => {
- this.value = v;
- // console.log('box updated value', v);
- });
- }
- });
- return { assertion: Observe(SetBox(_$)), analysis };
- });
- });
- thisFacet.spawn('client', function (thisFacet: Facet) {
- thisFacet.addEndpoint(() => {
- let analysis = Skeleton.analyzeAssertion(BoxState(_$));
- analysis.callback = thisFacet.wrap((thisFacet, evt, [v]) => {
- if (evt === Skeleton.EventType.ADDED) {
- if (typeof v !== 'number') return;
- thisFacet.scheduleScript(() => {
- // console.log('client sending SetBox', v + 1);
- thisFacet.send(SetBox(v + 1));
- });
- }
- });
- return { assertion: Observe(BoxState(_$)), analysis };
+ thisFacet.spawn('client', function (thisFacet: Facet<{}>) {
+ thisFacet.addEndpoint(function () {
+ let analysis = Skeleton.analyzeAssertion(BoxState(_$));
+ analysis.callback = thisFacet.wrap(function (thisFacet, evt, [v]) {
+ if (evt === Skeleton.EventType.ADDED) {
+ if (typeof v !== 'number') return;
+ thisFacet.scheduleScript(function () {
+ // console.log('client sending SetBox', v + 1);
+ thisFacet.send(SetBox(v + 1));
+ });
+ }
+ });
+ return { assertion: Observe(BoxState(_$)), analysis };
+ });
+ thisFacet.addEndpoint(function () {
+ let analysis = Skeleton.analyzeAssertion(BoxState(__));
+ analysis.callback = thisFacet.wrap(function (thisFacet, evt, _vs) {
+ if (evt === Skeleton.EventType.REMOVED) {
+ thisFacet.scheduleScript(function () {
+ console.log('box gone');
+ });
+ }
+ });
+ return { assertion: Observe(BoxState(__)), analysis };
+ });
});
- thisFacet.addEndpoint(() => {
- let analysis = Skeleton.analyzeAssertion(BoxState(__));
- analysis.callback = thisFacet.wrap((thisFacet, evt, _vs) => {
- if (evt === Skeleton.EventType.REMOVED) {
- thisFacet.scheduleScript(() => {
- console.log('box gone');
- });
- }
- });
- return { assertion: Observe(BoxState(__)), analysis };
- });
- });
- thisFacet.actor.dataspace.ground().addStopHandler(() =>
- console.timeEnd('box-and-client-' + N.toString()));
+ thisFacet.actor.dataspace.ground().addStopHandler(function () {
+ console.timeEnd('box-and-client-' + N.toString());
+ });
}
bootModule(boot);
diff --git a/packages/core/src/runtime/dataspace.ts b/packages/core/src/runtime/dataspace.ts
index c63fa49..1f42ef1 100644
--- a/packages/core/src/runtime/dataspace.ts
+++ b/packages/core/src/runtime/dataspace.ts
@@ -40,17 +40,18 @@ export type FacetId = ActorId;
export type EndpointId = ActorId;
export type Task = () => T;
-export type Script = (f: Facet) => T;
+export type Script = (this: Fields & DataflowObservableObject, f: Facet) => T;
export type MaybeValue = Value | undefined;
export type EndpointSpec = { assertion: MaybeValue, analysis: Skeleton.Analysis | null };
-export type ObserverCallback = (facet: Facet, bindings: Array) => void;
+export type ObserverCallback =
+ (this: Fields, facet: Facet, bindings: Array) => void;
-export type ObserverCallbacks = {
- add?: ObserverCallback;
- del?: ObserverCallback;
- msg?: ObserverCallback;
+export type ObserverCallbacks = {
+ add?: ObserverCallback;
+ del?: ObserverCallback;
+ msg?: ObserverCallback;
}
export const DataflowObservableObjectId = Symbol.for('DataflowObservableObjectId');
@@ -63,12 +64,12 @@ export function _canonicalizeDataflowObservable(i: DataflowObservable): string {
return i[0][DataflowObservableObjectId]() + ',' + i[1];
}
-export type DataflowDependent = Endpoint;
+export type DataflowDependent = Endpoint;
export function _canonicalizeDataflowDependent(i: DataflowDependent): string {
return '' + i.id;
}
-export type ActivationScript = Script;
+export type ActivationScript = Script;
export abstract class Dataspace {
nextId: ActorId = 0;
@@ -81,7 +82,7 @@ export abstract class Dataspace {
actors: IdentityMap = new IdentityMap();
activations: IdentitySet = new IdentitySet();
- constructor(bootProc: Script) {
+ constructor(bootProc: Script) {
this.pendingTurns = [new Turn(null, [new Spawn(null, bootProc, new Set())])];
}
@@ -129,7 +130,12 @@ export abstract class Dataspace {
});
}
- addActor(name: any, bootProc: Script, initialAssertions: Set, parentActor: Actor | null) {
+ addActor(
+ name: any,
+ bootProc: Script,
+ initialAssertions: Set,
+ parentActor: Actor | null)
+ {
let ac = new Actor(this, name, initialAssertions, parentActor?.id);
// debug('Spawn', ac && ac.toString());
this.applyPatch(ac, ac.adhocAssertions);
@@ -181,7 +187,7 @@ export abstract class Dataspace {
this.index.removeHandler(handler, handler.callback!);
}
- endpointHook(_facet: Facet, _endpoint: Endpoint) {
+ endpointHook(_facet: Facet, _endpoint: Endpoint) {
// Subclasses may override
}
}
@@ -190,7 +196,7 @@ export class Actor {
readonly id: ActorId;
readonly dataspace: Dataspace;
readonly name: any;
- rootFacet: Facet | null = null;
+ rootFacet: Facet | null = null;
isRunnable: boolean = false;
readonly pendingTasks: Array>>;
pendingActions: Array;
@@ -253,11 +259,15 @@ export class Actor {
this.pendingTasks[priority].push(task);
}
- addFacet(parentFacet: Facet | null, bootProc: Script, checkInScript: boolean = false) {
+ addFacet(
+ parentFacet: Facet | null,
+ bootProc: Script,
+ checkInScript: boolean = false)
+ {
if (checkInScript && parentFacet && !parentFacet.inScript) {
throw new Error("Cannot add facet outside script; are you missing a `react { ... }`?");
}
- let f = new Facet(this, parentFacet);
+ let f = new Facet(this, parentFacet);
f.invokeScript(f => f.withNonScriptContext(() => bootProc.call(f.fields, f)));
this.scheduleTask(() => {
if ((parentFacet && !parentFacet.isLive) || f.isInert()) {
@@ -351,12 +361,12 @@ class Message extends Action {
}
}
-class Spawn extends Action {
+class Spawn extends Action {
readonly name: any;
- readonly bootProc: Script;
+ readonly bootProc: Script;
readonly initialAssertions: Set;
- constructor(name: any, bootProc: Script, initialAssertions: Set = new Set()) {
+ constructor(name: any, bootProc: Script, initialAssertions: Set = new Set()) {
super();
this.name = name;
this.bootProc = bootProc;
@@ -406,7 +416,7 @@ class Activation extends Action {
perform(ds: Dataspace, ac: Actor | null): void {
if (ds.activations.has(this.script)) return;
ds.activations.add(this.script);
- ds.addActor(this.name, rootFacet => rootFacet.addStartScript(this.script), new Set(), ac);
+ ds.addActor<{}>(this.name, rootFacet => rootFacet.addStartScript(this.script), new Set(), ac);
}
}
@@ -424,18 +434,18 @@ export class Turn {
}
}
-export class Facet {
+export class Facet {
readonly id: FacetId;
isLive = true;
readonly actor: Actor;
- readonly parent: Facet | null;
- readonly endpoints = new IdentityMap();
- readonly stopScripts: Array