diff --git a/packages/eventual-send/src/E.js b/packages/eventual-send/src/E.js
index 889eccd0fd7..a984b2dfff8 100644
--- a/packages/eventual-send/src/E.js
+++ b/packages/eventual-send/src/E.js
@@ -1,13 +1,8 @@
-/* global globalThis window */
+/* global SES */
// eslint-disable-next-line spaced-comment
///
-// Shim globalThis when we don't have it.
-if (typeof globalThis === 'undefined') {
- const myGlobal = typeof window === 'undefined' ? global : window;
- myGlobal.globalThis = myGlobal;
-}
-const harden = (globalThis.SES && globalThis.SES.harden) || Object.freeze;
+const harden = (typeof SES !== 'undefined' && SES.harden) || Object.freeze;
const readOnlyProxy = {
set(_target, _prop, _value) {
@@ -57,103 +52,21 @@ function EProxyHandler(x, HandledPromise) {
export default function makeE(HandledPromise) {
function E(x) {
const handler = EProxyHandler(x, HandledPromise);
- return harden(new Proxy({}, handler));
+ return harden(new Proxy(() => {}, handler));
}
- const makeEGetterProxy = (x, wrap = o => o) =>
- new Proxy(Object.create(null), {
- ...readOnlyProxy,
- has(_target, _prop) {
- return true;
- },
- get(_target, prop) {
- return wrap(HandledPromise.get(x, prop));
- },
- });
-
- const makeEDeleterProxy = (x, wrap = o => o) =>
+ const makeEGetterProxy = x =>
new Proxy(Object.create(null), {
...readOnlyProxy,
has(_target, _prop) {
return true;
},
get(_target, prop) {
- return wrap(HandledPromise.delete(x, prop));
- },
- });
-
- const makeEHasProxy = (x, wrap = o => o) =>
- new Proxy(Object.create(null), {
- ...readOnlyProxy,
- has(_target, _prop) {
- return true;
- },
- get(_target, prop) {
- return wrap(HandledPromise.has(x, prop));
- },
- });
-
- const makeESetterProxy = (x, wrap = o => o) =>
- new Proxy(Object.create(null), {
- ...readOnlyProxy,
- has(_target, _prop) {
- return true;
- },
- get(_target, prop) {
- return harden(value => wrap(HandledPromise.set(x, prop, value)));
- },
- });
-
- const makeEMethodProxy = (x, wrap = o => o) =>
- new Proxy((..._args) => {}, {
- ...readOnlyProxy,
- has(_target, _prop) {
- return true;
- },
- get(_target, prop) {
- return harden((...args) =>
- wrap(HandledPromise.applyMethod(x, prop, args)),
- );
- },
- apply(_target, _thisArg, args = []) {
- return wrap(HandledPromise.applyFunction(x, args));
+ return HandledPromise.get(x, prop);
},
});
E.G = o => makeEGetterProxy(o);
- E.H = o => makeEHasProxy(o);
- E.D = o => makeEDeleterProxy(o);
- E.S = o => makeESetterProxy(o);
- E.M = o => makeEMethodProxy(o);
-
- const EChain = x =>
- harden({
- get G() {
- // Return getter.
- return makeEGetterProxy(x, EChain);
- },
- get D() {
- // Return deleter.
- return makeEDeleterProxy(x, EChain);
- },
- get H() {
- // Return has.
- return makeEHasProxy(x, EChain);
- },
- get S() {
- // Return setter.
- return makeESetterProxy(x, EChain);
- },
- get M() {
- // Return method-caller.
- return makeEMethodProxy(x, EChain);
- },
- get P() {
- // Return as promise.
- return Promise.resolve(x);
- },
- });
- E.C = EChain;
return harden(E);
}
diff --git a/packages/eventual-send/src/index.d.ts b/packages/eventual-send/src/index.d.ts
index d5fce17a393..74f93839dd4 100644
--- a/packages/eventual-send/src/index.d.ts
+++ b/packages/eventual-send/src/index.d.ts
@@ -21,47 +21,13 @@ interface HandledPromiseConstructor {
declare const HandledPromise: HandledPromiseConstructor;
-interface ESingleMethod {
- [prop: Property]: (...args) => U;
+interface ESingleMethod {
+ (...args: unknown[]): Promise;
+ [prop: Property]: (...args) => Promise;
}
-interface EChain {
- M: EChainMethod>;
- G: EChainGet>;
- S: EChainSet>;
- D: EChainDelete>;
- P: Promise;
- sendOnly: EChainSendOnly;
-}
-
-interface EChainSendOnly {
- M: EChainMethod;
- G: EChainGet;
- S: EChainSet;
- D: EChainDelete;
-}
-
-interface EChainMethod {
- (...args: unknown[]): U;
- [prop: Property]: (...args: unknown) => U;
-}
-
-interface EChainGet {
- [prop: Property]: U;
-}
-
-interface EChainSet {
- /**
- * Eventually set the prop property.
- */
- [prop: Property]: (value: unknown) => U;
-}
-
-interface EChainDelete {
- /**
- * Eventually delete the prop property.
- */
- [prop: Property]: U is void ? U : EChain;
+interface ESingleGet {
+ [prop: Property]: Promise;
}
interface EProxy {
@@ -74,16 +40,18 @@ interface EProxy {
* @param {*} x target for method call
* @returns {ESingleMethod} method call proxy
*/
- (x: unknown): ESingleMethod>;
- sendOnly: (x: unknown) => ESingleMethod;
+ (x: unknown): ESingleMethod;
+ sendOnly: (x: unknown) => ESingleMethod;
/**
- * E.C(x) returns a chain where operations are selected by
- * uppercase single-letter selectors.
+ * E.G(x) returns a proxy on which you can get arbitrary properties.
+ * Each of these properties returns a promise. The property will be
+ * taken from whatever 'x' designates (or resolves to) in a future turn,
+ * not this one.
*
- * @param {*} x target for first operation
- * @returns {EChain}
+ * @param {*} x target for property get
+ * @returns {ESingleGet} property get proxy
*/
- C(x: unknown): EChain;
+ G(x: unknown): ESingleGet;
}
export const E: EProxy;
diff --git a/packages/eventual-send/src/index.js b/packages/eventual-send/src/index.js
index 824e6a218b2..14da0151908 100644
--- a/packages/eventual-send/src/index.js
+++ b/packages/eventual-send/src/index.js
@@ -1,4 +1,4 @@
-/* global globalThis */
+/* global HandledPromise SES globalThis window */
import makeE from './E';
@@ -8,18 +8,27 @@ import makeE from './E';
// import { HandledPromise, E } from '@agoric/eventual-send';
// ...
-// TODO: Maybe rename the global HandledPromise to something only the tildot rewriter uses.
-if (!globalThis.HandledPromise) {
+// eslint-disable-next-line import/no-mutable-exports
+let hp;
+if (typeof HandledPromise === 'undefined') {
/* eslint-disable no-use-before-define */
+ if (typeof globalThis === 'undefined') {
+ const myGlobal = typeof window === 'undefined' ? global : window;
+ myGlobal.globalThis = window;
+ }
+
// Install the shim as best we can.
maybeExtendPromise(Promise);
globalThis.HandledPromise = makeHandledPromise(Promise);
+ hp = globalThis.HandledPromise;
/* eslint-enable no-use-before-define */
+} else {
+ hp = HandledPromise;
}
// Provide a handled platform Promise if SES has not run.
-export const { HandledPromise } = globalThis;
-export const E = makeE(HandledPromise);
+export { hp as HandledPromise };
+export const E = makeE(hp);
// the following methods (makeHandledPromise and maybeExtendPromise) are part
// of the shim, and will not be exported by the module once the feature
@@ -28,10 +37,10 @@ export const E = makeE(HandledPromise);
// Create HandledPromise static methods as a bridge from v0.2.4
// to new proposal support (wavy dot's infrastructure).
export function makeHandledPromise(EPromise) {
- const harden = (globalThis.SES && globalThis.SES.harden) || Object.freeze;
+ const harden = (typeof SES !== 'undefined' && SES.harden) || Object.freeze;
- // TODO: Use HandledPromise.resolve to store our weakmap, and
- // install it on Promise.resolve.
+ // TODO: Use HandledPromise.resolve to store our weakmap, instead of
+ // monkey-patching Promise.resolve.
const staticMethods = {
get(target, key) {
return EPromise.resolve(target).get(key);
@@ -39,25 +48,6 @@ export function makeHandledPromise(EPromise) {
getSendOnly(target, key) {
EPromise.resolve(target).get(key);
},
- has(target, key) {
- return EPromise.resolve(target).has(key);
- },
- hasSendOnly(target, key) {
- EPromise.resolve(target).has(key);
- },
- set(target, key, val) {
- return EPromise.resolve(target).put(key, val);
- },
- setSendOnly(target, key, val) {
- EPromise.resolve(target).put(key, val);
- },
- // TODO: Change HandledPromise.delete to HandledPromise.deleteProperty
- delete(target, key) {
- return EPromise.resolve(target).delete(key);
- },
- deleteSendOnly(target, key) {
- EPromise.resolve(target).delete(key);
- },
applyFunction(target, args) {
return EPromise.resolve(target).post(undefined, args);
},
@@ -161,18 +151,6 @@ export function maybeExtendPromise(Promise) {
return handle(this, 'GET', key);
},
- has(key) {
- return handle(this, 'HAS', key);
- },
-
- put(key, val) {
- return handle(this, 'PUT', key, val);
- },
-
- delete(key) {
- return handle(this, 'DELETE', key);
- },
-
post(optKey, args) {
return handle(this, 'POST', optKey, args);
},
@@ -261,9 +239,6 @@ export function maybeExtendPromise(Promise) {
unfulfilledHandler = {
GET: makePostponed('get'),
- HAS: makePostponed('has'),
- PUT: makePostponed('put'),
- DELETE: makePostponed('delete'),
POST: makePostponed('post'),
};
}
@@ -391,9 +366,6 @@ export function maybeExtendPromise(Promise) {
forwardingHandler = {
GET: makeForwarder('GET', (o, key) => o[key]),
- HAS: makeForwarder('HAS', (o, key) => key in o),
- PUT: makeForwarder('PUT', (o, key, val) => (o[key] = val)),
- DELETE: makeForwarder('DELETE', (o, key) => delete o[key]),
POST: makeForwarder('POST', (o, optKey, args) => {
if (optKey === undefined || optKey === null) {
return o(...args);
diff --git a/packages/eventual-send/test/test-e.js b/packages/eventual-send/test/test-e.js
index 116f2c369d9..96ef0db3e3c 100644
--- a/packages/eventual-send/test/test-e.js
+++ b/packages/eventual-send/test/test-e.js
@@ -18,7 +18,7 @@ test('E method calls', async t => {
}
});
-test('E.* shortcuts', async t => {
+test('E shortcuts', async t => {
try {
const x = {
name: 'buddy',
@@ -32,56 +32,13 @@ test('E.* shortcuts', async t => {
return `${greeting}, ${this.name}!`;
},
};
- t.equal(await E.M(x).hello('Hello'), 'Hello, buddy!', 'method call works');
+ t.equal(await E(x).hello('Hello'), 'Hello, buddy!', 'method call works');
t.equal(
- await E.M(await E.G(await E.G(x).y).fn)(4),
+ await E(await E.G(await E.G(x).y).fn)(4),
8,
'anonymous method works',
);
t.equal(await E.G(x).val, 123, 'property get');
- t.equal(await E.S(x).val(999), 999, 'property set');
- t.equal(x.val, 999, 'property set works');
- t.equal(await E.D(x).val, true, 'property delete');
- t.equal(x.val, undefined, 'delete worked');
- await t.rejects(
- E.D(await E.G(x).y).val2,
- TypeError,
- 'property delete fails',
- );
- t.equal(x.y.val2, 456, 'delete failed');
- } catch (e) {
- t.isNot(e, e, 'unexpected exception');
- } finally {
- t.end();
- }
-});
-
-test('E.C chains', async t => {
- try {
- const x = {
- name: 'buddy',
- val: 123,
- y: Object.freeze({
- val2: 456,
- name2: 'holly',
- fn: n => 2 * n,
- }),
- hello(greeting) {
- return `${greeting}, ${this.name}!`;
- },
- };
- const xC = E.C(x);
- t.equal(await xC.M.hello('Hello').P, 'Hello, buddy!', 'method call works');
- t.equal(await xC.G.y.G.fn.M(4).P, 8, 'anonymous method works');
- t.equal(await xC.G.val.P, 123, 'property get');
- t.equal(await xC.S.val(999).P, 999, 'property set');
- t.equal(await xC.H.val.P, true, 'property has');
- t.equal(await xC.H.notval.P, false, 'missing property has not');
- t.equal(x.val, 999, 'property set works');
- t.equal(await xC.D.val.P, true, 'property delete');
- t.equal(x.val, undefined, 'delete worked');
- await t.rejects(xC.G.y.D.val2.P, TypeError, 'property delete fails');
- t.equal(x.y.val2, 456, 'delete failed');
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
diff --git a/packages/eventual-send/test/test.js b/packages/eventual-send/test/test.js
index 946370092ce..bdce1fc33d4 100644
--- a/packages/eventual-send/test/test.js
+++ b/packages/eventual-send/test/test.js
@@ -153,12 +153,6 @@ test('Promise.makeHandled expected errors', async t => {
GET(key) {
return key;
},
- DELETE(_key) {
- return true;
- },
- PUT(key, value) {
- return value;
- },
POST(key, args) {
return args;
},
@@ -188,16 +182,6 @@ test('Promise.makeHandled expected errors', async t => {
`missing ${method} defaults`,
);
break;
- case 'PUT':
- t.equals(
- await Promise.makeHandled((_, _2, rwp) => rwp(handler2)).put(
- 'foo',
- 123,
- ),
- 123,
- `missing ${method} defaults`,
- );
- break;
case 'POST':
t.equals(
await Promise.makeHandled((_, _2, rwp) => {
@@ -212,15 +196,6 @@ test('Promise.makeHandled expected errors', async t => {
`missing ${method} defaults`,
);
break;
- case 'DELETE':
- t.equals(
- await Promise.makeHandled((_, _2, rwp) => rwp(handler2)).delete(
- 'foo',
- ),
- true,
- `missing ${method} defaults`,
- );
- break;
default:
throw TypeError(`Unrecognized method type ${method}`);
}
@@ -257,12 +232,6 @@ test('Promise.makeHandled(executor, undefined)', async t => {
GET(p, key) {
return o[key];
},
- PUT(p, key, value) {
- return (o[key] = value);
- },
- DELETE(p, key) {
- return delete o[key];
- },
POST(p, key, args) {
return o[key](...args);
},
@@ -278,16 +247,6 @@ test('Promise.makeHandled(executor, undefined)', async t => {
);
t.equal(await handledP.get('str'), 'my string', `.get works`);
t.equal(await handledP.get('num'), 123, `.get num works`);
- t.equal(await handledP.put('num', 789), 789, `.put works`);
- t.equal(await handledP.get('num'), 789, `.put changes assignment`);
- t.equal(await handledP.delete('str'), true, `.delete works`);
- t.equal(await handledP.get('str'), undefined, `.delete actually deletes`);
- t.equal(await handledP.delete('str'), true, `.delete works second time`);
- t.equal(
- await handledP.get('str'),
- undefined,
- `.delete second time still deletes`,
- );
t.equal(
await handledP.invoke('hello', 'World'),
'Hello, World',
@@ -427,19 +386,6 @@ test('get', async t => {
}
});
-test('put', async t => {
- try {
- const a = [123, 456, 789];
- const ep = Promise.resolve(a);
- t.equal(await ep.put(1, 999), 999, `.put works`);
- t.deepEqual(a, [123, 999, 789], `.put actually changed`);
- } catch (e) {
- t.assert(false, `Unexpected exception ${e}`);
- } finally {
- t.end();
- }
-});
-
test('post', async t => {
try {
const fn = () => 'hello';