Skip to content

Commit 3e63758

Browse files
committed
fix(lockdown): Begin working toward lockdown-style SES API
1 parent f2a3206 commit 3e63758

File tree

3 files changed

+87
-17
lines changed

3 files changed

+87
-17
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"prettier": "yarn workspaces run prettier",
5454
"link-cli": "node ./scripts/link-cli.js",
5555
"lint-fix": "yarn workspaces run lint-fix",
56-
"lint-check": "cd packages/marshal && yarn lint-check && cd ../SwingSet && yarn lint-check && cd ../ERTP && yarn lint-check && cd ../zoe && yarn lint-check && cd ../acorn-eventual-send && yarn lint-check && cd ../eventual-send && yarn lint-check && cd ../transform-eventual-send && yarn lint-check && cd ../transform-metering && yarn lint-check && cd ../default-evaluate-options && yarn lint-check && cd ../evaluate && yarn lint-check && cd ../bundle-source && yarn lint-check && cd ../captp && yarn lint-check",
56+
"lint-check": "cd packages/marshal && yarn lint-check && cd ../SwingSet && yarn lint-check && cd ../ERTP && yarn lint-check && cd ../zoe && yarn lint-check && cd ../acorn-eventual-send && yarn lint-check && cd ../eventual-send && yarn lint-check && cd ../transform-eventual-send && yarn lint-check && cd ../tame-metering && yarn lint-check && cd ../transform-metering && yarn lint-check && cd ../default-evaluate-options && yarn lint-check && cd ../evaluate && yarn lint-check && cd ../bundle-source && yarn lint-check && cd ../captp && yarn lint-check",
5757
"lint-check-all": "yarn workspaces run lint-check",
5858
"test": "yarn workspaces run test",
5959
"build": "yarn workspaces run build"

packages/tame-metering/src/tame.js

+25-12
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import * as c from './constants';
44
const {
55
defineProperties,
66
entries,
7-
fromEntries,
87
getOwnPropertyDescriptors,
8+
getPrototypeOf,
9+
setPrototypeOf,
910
} = Object;
1011
const { apply, construct, get } = Reflect;
1112
const { get: wmGet, set: wmSet } = WeakMap.prototype;
@@ -29,16 +30,16 @@ export default function tameMetering() {
2930
setWrapped(Error, Error); // FIGME: debugging
3031
setWrapped(console, console); // FIGME
3132
*/
32-
const wrapDescriptor = desc => {
33+
const wrapDescriptor = (desc, pname = undefined) => {
3334
const newDesc = {};
3435
for (const [k, v] of entries(desc)) {
3536
// eslint-disable-next-line no-use-before-define
36-
newDesc[k] = wrap(v);
37+
newDesc[k] = wrap(v, pname && `${pname}.${k}`);
3738
}
3839
return newDesc;
3940
};
4041

41-
function wrap(target) {
42+
function wrap(target, pname) {
4243
if (ObjectConstructor(target) !== target) {
4344
return target;
4445
}
@@ -63,7 +64,7 @@ export default function tameMetering() {
6364

6465
// Track the entry of the stack frame.
6566
globalMeter = null;
66-
// savedMeter && savedMeter[c.METER_ENTER](undefined, false);
67+
/* savedMeter && savedMeter[c.METER_ENTER](undefined, false); */
6768
savedMeter && savedMeter[c.METER_COMPUTE](undefined, false);
6869
let ret;
6970

@@ -105,25 +106,37 @@ export default function tameMetering() {
105106
wrapper = target;
106107
}
107108

108-
// We have a wrapper identity, so prevent recursion.
109+
// We have a wrapper identity, so prevent recursion by installing it now.
109110
setWrapped(target, wrapper);
110111
setWrapped(wrapper, wrapper);
111112

112113
if (isFunction) {
113-
// Replace the constructor.
114114
const proto = get(target, 'prototype');
115+
115116
if (proto) {
116-
const wproto = wrap(proto);
117+
// Replace the constructor.
118+
const wproto = wrap(proto, pname && `${pname}.prototype`);
117119
wproto.constructor = wrapper;
118120
}
119121
}
120122

123+
// Ensure the prototype chain is also wrapped.
124+
setPrototypeOf(
125+
wrapper,
126+
wrap(getPrototypeOf(target), pname && `${pname}.__proto__`),
127+
);
128+
121129
// Assign the wrapped descriptors to the wrapper.
122-
const props = entries(
123-
getOwnPropertyDescriptors(target),
124-
).map(([p, desc]) => [p, wrapDescriptor(desc)]);
125-
defineProperties(wrapper, fromEntries(props));
130+
const descs = {};
131+
for (const [p, desc] of entries(getOwnPropertyDescriptors(target))) {
132+
const desc2 = wrapDescriptor(desc, pname && `${pname}.${p}`);
133+
if (isFunction && p === 'name') {
134+
desc2.value = target.name;
135+
}
136+
descs[p] = desc2;
137+
}
126138

139+
defineProperties(wrapper, descs);
127140
return wrapper;
128141
}
129142

packages/transform-metering/test/test-zzz-eval.js

+61-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,73 @@
1-
import replaceGlobalMeter from '@agoric/tame-metering/src/install-global-metering';
1+
// import replaceGlobalMeter from '@agoric/tame-metering/src/install-global-metering';
2+
import * as tamer from '@agoric/tame-metering/src/install-global-metering';
3+
import * as c from '@agoric/tame-metering/src/constants';
24

35
import test from 'tape-promise/tape';
46
import * as babelCore from '@babel/core';
5-
import SES from 'ses';
7+
import * as ses from 'ses';
68

79
import { makeMeter, makeMeteredEvaluator } from '../src/index';
810

911
let sesRealm;
12+
let replaceGlobalMeter;
1013
if (!sesRealm) {
11-
// FIXME: lockdown() approach is the only way to both secure
14+
// FIXME: lockdown() approach appears to be the only way to both secure
1215
// this realm and make meters available to evaluators.
13-
sesRealm = SES.makeSESRootRealm();
16+
const { lockdown, default: SES } = ses;
17+
const { tameMetering, default: globalReplaceGlobalMeter } = tamer;
18+
if (tameMetering && !lockdown) {
19+
const shim = `\
20+
(() => {
21+
const globalThis = this;
22+
23+
const c = ${JSON.stringify(c)}
24+
let replaceGlobalMeter;
25+
const ObjectConstructor = Object;
26+
const {
27+
create,
28+
defineProperties,
29+
entries,
30+
isExtensible,
31+
getOwnPropertyDescriptors,
32+
getPrototypeOf,
33+
setPrototypeOf,
34+
} = Object;
35+
const { apply, construct, get } = Reflect;
36+
const { get: wmGet, set: wmSet } = WeakMap.prototype;
37+
38+
(${tamer.tameMetering})();
39+
40+
let neutered;
41+
this.Q = () => {
42+
if (!neutered) {
43+
neutered = true;
44+
return replaceGlobalMeter;
45+
}
46+
throw Error('Cannot execute twice');
47+
};
48+
})()`;
49+
sesRealm = SES.makeSESRootRealm({
50+
consoleMode: 'allow',
51+
errorStackMode: 'allow',
52+
shims: [shim],
53+
});
54+
replaceGlobalMeter = sesRealm.evaluate('Q()');
55+
} else if (!lockdown) {
56+
// We already tamed globally.
57+
sesRealm = SES.makeSESRootRealm({
58+
consoleMode: 'allow',
59+
errorStackMode: 'allow',
60+
});
61+
replaceGlobalMeter = globalReplaceGlobalMeter;
62+
} else if (tameMetering) {
63+
// FIXME: How to get sesRealm?
64+
replaceGlobalMeter = tameMetering();
65+
lockdown();
66+
} else {
67+
// FIXME: How to get sesRealm?
68+
replaceGlobalMeter = tamer.default;
69+
lockdown();
70+
}
1471
}
1572

1673
export const makeSESEvaluator = opts =>

0 commit comments

Comments
 (0)