Skip to content

Commit 62786fc

Browse files
committed
chore(ses): add missing types to main compartment implementation
1 parent 37d948e commit 62786fc

File tree

3 files changed

+94
-33
lines changed

3 files changed

+94
-33
lines changed

packages/ses/src-xs/compartment.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ import { tameFunctionToString } from '../src/tame-function-tostring.js';
3030
import { chooseReporter } from '../src/reporting.js';
3131
import { makeError } from '../src/error/assert.js';
3232

33+
/**
34+
* @import {CompartmentOptionsArgs, LegacyCompartmentOptionsArgs} from '../src/compartment.js'
35+
*/
36+
3337
const muteReporter = chooseReporter('none');
3438

3539
export const ShimStartCompartment = makeCompartmentConstructor(
@@ -178,6 +182,7 @@ export const adaptCompartmentConstructors = (
178182
ShimCompartment,
179183
maybeHarden,
180184
) => {
185+
/** @param {CompartmentOptionsArgs|LegacyCompartmentOptionsArgs} args */
181186
function Compartment(...args) {
182187
const options = compartmentOptions(...args);
183188

packages/ses/src/compartment.js

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939

4040
// @ts-check
4141
/* eslint-disable no-underscore-dangle */
42-
/// <reference types="ses">
4342

4443
import {
4544
Map,
@@ -68,17 +67,49 @@ import { getDeferredExports } from './module-proxy.js';
6867
import { compartmentEvaluate } from './compartment-evaluate.js';
6968
import { makeSafeEvaluator } from './make-safe-evaluator.js';
7069

71-
/** @import {ModuleDescriptor, ModuleExportsNamespace} from '../types.js' */
70+
/**
71+
* @import {ImportHook, ImportMetaHook, ImportNowHook, ModuleDescriptor, ModuleExportsNamespace, ModuleMap, ModuleMapHook, ResolveHook, ModuleSource, CompartmentOptions} from '../types.js'
72+
* @import {Transform} from './lockdown.js'
73+
* @import {DeferredExports} from './module-proxy.js'
74+
*/
7275

73-
// moduleAliases associates every public module exports namespace with its
74-
// corresponding compartment and specifier so they can be used to link modules
75-
// across compartments.
76-
// The mechanism to thread an alias is to use the compartment.module function
77-
// to obtain the exports namespace of a foreign module and pass it into another
78-
// compartment's moduleMap constructor option.
76+
/**
77+
* Associates every public module exports namespace with its corresponding
78+
* compartment and specifier so they can be used to link modules across
79+
* compartments. The mechanism to thread an alias is to use the
80+
* {@link Compartment.module} function to obtain the exports namespace of a foreign
81+
* module and pass it into another compartment's `moduleMap` constructor option
82+
* @type {WeakMap<ModuleExportsNamespace, Compartment>}
83+
*
84+
*/
7985
const moduleAliases = new WeakMap();
8086

81-
// privateFields captures the private state for each compartment.
87+
/**
88+
* Private fields for `Compartment` instances
89+
* @typedef {object} CompartmentFields
90+
* @property {string} name
91+
* @property {object} globalObject
92+
* @property {Array<Transform>} globalTransforms
93+
* @property {(source: string, options?: {localTransforms?: Array<Transform>}) => void} safeEvaluate
94+
* @property {ResolveHook} resolveHook
95+
* @property {ImportHook} importHook
96+
* @property {ImportNowHook} importNowHook
97+
* @property {ModuleMap} moduleMap
98+
* @property {ModuleMapHook} moduleMapHook
99+
* @property {ImportMetaHook} importMetaHook
100+
* @property {Map<string, ModuleSource>} moduleRecords
101+
* @property {Array<Transform>} __shimTransforms__
102+
* @property {DeferredExports} deferredExports
103+
* @property {Map<string, ModuleDescriptor>} instances
104+
* @property {Compartment} [parentCompartment]
105+
* @property {boolean} noNamespaceBox
106+
* @property {(fullSpecifier: string) => Promise<ModuleExportsNamespace>} compartmentImport
107+
*/
108+
109+
/**
110+
* Captures the private state for each {@link Compartment}
111+
* @type {WeakMap<Compartment, CompartmentFields>}
112+
*/
82113
const privateFields = new WeakMap();
83114

84115
export const InertCompartment = function Compartment(
@@ -94,6 +125,7 @@ export const InertCompartment = function Compartment(
94125
/**
95126
* @param {Compartment} compartment
96127
* @param {string} specifier
128+
* @returns {{namespace: ModuleExportsNamespace}}
97129
*/
98130
const compartmentImportNow = (compartment, specifier) => {
99131
const { execute, exportsProxy } = link(
@@ -106,27 +138,20 @@ const compartmentImportNow = (compartment, specifier) => {
106138
return exportsProxy;
107139
};
108140

141+
/** @type {Compartment & {constructor: typeof InertCompartment}} */
109142
export const CompartmentPrototype = {
110143
constructor: InertCompartment,
111144

112145
get globalThis() {
113-
return weakmapGet(privateFields, this).globalObject;
146+
return /** @type {CompartmentFields} */ (weakmapGet(privateFields, this))
147+
.globalObject;
114148
},
115149

116150
get name() {
117-
return weakmapGet(privateFields, this).name;
151+
return /** @type {CompartmentFields} */ (weakmapGet(privateFields, this))
152+
.name;
118153
},
119154

120-
/**
121-
* @param {string} source is a JavaScript program grammar construction.
122-
* @param {object} [options]
123-
* @param {Array<import('./lockdown-shim').Transform>} [options.transforms]
124-
* @param {boolean} [options.sloppyGlobalsMode]
125-
* @param {object} [options.__moduleShimLexicals__]
126-
* @param {boolean} [options.__evadeHtmlCommentTest__]
127-
* @param {boolean} [options.__evadeImportExpressionTest__]
128-
* @param {boolean} [options.__rejectSomeDirectEvalExpressions__]
129-
*/
130155
evaluate(source, options = {}) {
131156
const compartmentFields = weakmapGet(privateFields, this);
132157
return compartmentEvaluate(compartmentFields, source, options);
@@ -148,7 +173,9 @@ export const CompartmentPrototype = {
148173
},
149174

150175
async import(specifier) {
151-
const { noNamespaceBox } = weakmapGet(privateFields, this);
176+
const { noNamespaceBox } = /** @type {CompartmentFields} */ (
177+
weakmapGet(privateFields, this)
178+
);
152179

153180
if (typeof specifier !== 'string') {
154181
throw TypeError('first argument of import() must be a string');
@@ -187,7 +214,7 @@ export const CompartmentPrototype = {
187214
}
188215

189216
loadNow(privateFields, moduleAliases, this, specifier);
190-
return compartmentImportNow(/** @type {Compartment} */ (this), specifier);
217+
return compartmentImportNow(this, specifier);
191218
},
192219
};
193220

@@ -218,15 +245,35 @@ defineProperties(InertCompartment, {
218245
* @returns {Compartment['constructor']}
219246
*/
220247

221-
// In order to facilitate migration from the deprecated signature
222-
// of the compartment constructor,
223-
// new Compartent(globals?, modules?, options?)
224-
// to the new signature:
225-
// new Compartment(options?)
226-
// where globals and modules are expressed in the options bag instead of
227-
// positional arguments, this function detects the temporary sigil __options__
228-
// on the first argument and coerces compartments arguments into a single
229-
// compartments object.
248+
/**
249+
* "Options bag"-style `Compartment` constructor arguments.
250+
* @typedef {[options?: CompartmentOptions & { __options__: true }]} CompartmentOptionsArgs
251+
*/
252+
253+
/**
254+
* Legacy `Compartment` constructor arguments.
255+
*
256+
* @deprecated
257+
* @typedef {[globals?: Map<string, any>, modules?: Map<string, ModuleDescriptor>, options?: CompartmentOptions]} LegacyCompartmentOptionsArgs
258+
*/
259+
260+
/**
261+
* In order to facilitate migration from the deprecated signature of the
262+
* compartment constructor,
263+
*
264+
* `new Compartent(globals?, modules?, options?)`
265+
*
266+
* to the new signature:
267+
*
268+
* `new Compartment(options?)`
269+
*
270+
* ...where globals and modules are expressed in the options bag instead of
271+
* positional arguments, this function detects the temporary sigil __options__
272+
* on the first argument and coerces compartments arguments into a single
273+
* compartments object.
274+
* @param {CompartmentOptionsArgs|LegacyCompartmentOptionsArgs} args
275+
* @returns {CompartmentOptions}
276+
*/
230277
export const compartmentOptions = (...args) => {
231278
if (args.length === 0) {
232279
return {};
@@ -248,7 +295,7 @@ export const compartmentOptions = (...args) => {
248295
globals = /** @type {Map<string, any>} */ ({}),
249296
modules = /** @type {Map<string, ModuleDescriptor>} */ ({}),
250297
options = {},
251-
] = args;
298+
] = /** @type {LegacyCompartmentOptionsArgs} */ (args);
252299
assertEqual(
253300
options.modules,
254301
undefined,
@@ -274,6 +321,10 @@ export const makeCompartmentConstructor = (
274321
markVirtualizedNativeFunction,
275322
{ parentCompartment = undefined, enforceNew = false } = {},
276323
) => {
324+
/**
325+
*
326+
* @param {CompartmentOptionsArgs|LegacyCompartmentOptionsArgs} args
327+
*/
277328
function Compartment(...args) {
278329
if (enforceNew && new.target === undefined) {
279330
throw TypeError(

packages/ses/types.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ export interface CompartmentOptions {
167167
modules?: Map<string, ModuleDescriptor>;
168168
__shimTransforms__?: Array<Transform>;
169169
__noNamespaceBox__?: boolean;
170+
/** @deprecated */
171+
loadHook?: (specifier: string) => Promise<ModuleDescriptor>;
172+
/** @deprecated */
173+
loadNowHook?: (specifier: string) => ModuleDescriptor;
174+
__native__?: boolean;
170175
}
171176

172177
export interface EvaluateOptions {

0 commit comments

Comments
 (0)