Skip to content

Instantly share code, notes, and snippets.

@zarutian
Last active November 20, 2023 15:59
Show Gist options
  • Save zarutian/3c6939c339d832b2460897eb70d4a082 to your computer and use it in GitHub Desktop.
Save zarutian/3c6939c339d832b2460897eb70d4a082 to your computer and use it in GitHub Desktop.
// https://gist.github.com/zarutian/6ac6b7576af041dd5dc5b95f1f8d1f0f#file-certchequeexecutor-js-L50-L129
// https://github.com/endojs/endo/blob/master/packages/eventual-send/src/handled-promise.js
// this thing builds a certain kind of seqBlock from eventual sends
((require, module, exports) => {
const harden = (specimen) => specimen; // stop-gap until harden is imported
const { HandledPromise, E } = require("@endojs/endo/eventual-send");
exports.makeSeqBlockFromERef = (opts = {}) => {
let collecting_eventual_sends = true;
const assert_collecting = () => {
if (collecting_eventual_sends) {
return;
} else {
throw new Error("no longer collecting eventual sends");
}
};
const seqBlockBody = []; // FlexList
let qid_counter = 0;
const nextQID = () => {
qid_counter = qid_counter + 1;
return qid_counter;
};
const thing2i = new Map();
const resolvers = new WeakMap();
const pendingHandler = {
get: (target, propertyKey, returnedPromise) => {
assert_collecting();
let resolver;
{ promise: returnedPromise, resolver } = makeMyHandledPromise();
resolvers.set(returnedPromise, resolver);
const qid = nextQID();
const prop = thing2i.has(propertyKey) ? thing2i.get(propertyKey) : ["@dat", propertyKey];
seqBlockBody.push(
["get", qid, thing2i.get(target), prop],
);
thing2i.set(returnPromise, ["@qid", qid]);
return returnedPromise;
},
getSendOnly: (target, propertyKey) => {
assert_collecting();
const prop = thing2i.has(propertyKey) ? thing2i.get(propertyKey) : ["@dat", propertyKey];
seqBlockBody.push(
["get", nextQID(), thing2i.get(target), prop],
);
return undefined;
},
setSendOnly: (target, propertyKey, newValue) => {
// throw new Error("not yet implemented");
assert_collecting();
const prop = thing2i.has(propertyKey) ? thing2i.get(propertyKey) : ["@dat", propertyKey];
const valu = thing2i.has(newValue) ? thing2i.get(newValue) : ["@dat", newValue];
seqBlockBody.push(
["setSendOnly", thing2i.get(target), prop, valu],
);
return undefined;
},
applyFunction: (target, args, returnedPromise) => {
assert_collecting();
let resolver;
{ promise: returnedPromise, resolver } = makeMyHandledPromise();
resolvers.set(returnedPromise, resolver);
const qid = nextQID();
const argus = args.map((a) => (thing2i.has(a) ? thing2i.get(a) : ["@dat", a]));
argus.unshift("@arr");
seqBlockBody.push(
["applyFunction", qid, thing2i.get(target), argus],
);
thing2i.set(returnedPromise, ["@qid", qid]);
return returnedPromise;
},
applyFunctionSendOnly: (target, args) => {
assert_collecting();
const argus = args.map((a) => (thing2i.has(a) ? thing2i.get(a) : ["@dat", a]));
argus.unshift("@arr");
seqBlockBody.push(
["applyFunctionSendOnly", thing2i.get(target), argus],
);
return undefined;
},
applyMethod: (target, verb, args, returnedPromise) => {
assert_collecting();
let resolver;
{ promise: returnedPromise, resolver } = makeMyHandledPromise();
resolvers.set(returnedPromise, resolver);
const qid = nextQID();
const argus = args.map((a) => (thing2i.has(a) ? thing2i.get(a) : ["@dat", a]));
argus.unshift("@arr");
seqBlockBody.push(
["applyMethod", qid, thing2i.get(target), verb, argus],
);
thing2i.set(returnedPromise, ["@qid", qid]);
return returnedPromise;
},
applyMethodSendOnly: (target, verb, args) => {
assert_collecting();
const argus = args.map((a) => (thing2i.has(a) ? thing2i.get(a) : ["@dat", a]));
argus.unshift("@arr");
seqBlockBody.push(
["applyMethodSendOnly", thing2i.get(target), verb, argus],
);
return undefined;
},
when: (target, onResolve, onReject) => {
// for E.when(myHandledPromise, onResolve, onReject)
const qid = nextQID();
let { promise: returnedPromise, resolver } = makeMyHandledPromise();
resolvers.set(returnedPromise, resolver);
const t5 = ["@arr",
["@arr", ["@dat", "applyFunction"], ["@dat", "q1"], ["@ref", onReject], ["@arr", ["@dat", "@arr"], ["@arr", ["@dat", "@sba"], ["@dat", 0]]]],
["@arr", ["@dat", "applyFunctionSendOnly"], ["@ref", resolver.reject], ["@arr", ["@dat", "@arr"], ["@arr", ["@dat", "@qid"], ["@dat", "q1"]]]],
];
const t4 = ["@arr",
["@arr", ["@dat", "applyFunction"], ["@dat", "q1"], ["@ref", onResolve], ["@arr", ["@dat", "@arr"], ["@arr", ["@dat", "@sba"], ["@dat", 0]]]],
["@arr", ["@dat", "applyFunctionSendOnly"], ["@ref", resolver.resolve], ["@arr", ["@dat", "@arr"], ["@arr", ["@dat", "@qid"], ["@dat", "q1"]]]],
];
const t3 = ["@sqb", t5, ["@env"]];
const t2 = ["@sqb", t4, ["@env"]];
const t1 = ["@rec", ["@dat", "resolve"], t2, ["@dat", "reject"], t3];
seqBlockBody.push(
["applyFunction", qid, ["@env", "async_listen"], ["@arr", thing2i.get(target), t1]],
);
thing2i.set(returnedPromise, ["@qid", qid]);
return returnedPromise;
},
where: (target, nomad) => {
// for E.where(myHandledPromise, nomad)
const qid = nextQID();
let { promise: returnedPromise, resolver } = makeMyHandledPromise();
resolvers.set(returnedPromise, resolver);
seqBlockBody.push(
["assignOnce", qid, ["@dat", nomad]],
);
thing2i.set(returnedPromise, ["@qid", qid]);
return returnedPromise;
},
};
const makeMyHandledPromise = () => {
let resolver = undefined;
const promise = new HandledPromise((resolve, reject, resolveWithPresence) => {
resolver = { resolve, reject, resolveWithPresence};
}, pendingHandler);
return { promise, resolver };
};
const { promise: rootref, resolver: rootresolver } = makeMyHandledPromise();
thing2i.set(rootref, ["@sba", 0]);
const getSeqBlock = () => {
collecting_eventual_sends = false;
return harden(seqBlockBody);
};
return { rootref, getSeqBlock };
};
return exports;
})(require, {}, {});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment