Skip to content

Commit b6314c2

Browse files
committed
fix(module-source,compartment-mapper): fix SourceMapHook & other types
This fixes the type of `SourceMapHook` and the implementation to align with reality. - Introduces some `.ts` sources for types; fixes `tsconfig.json` - Fixes exports of said types - Fixes shim types - Adds a `typedoc.json` for proper entry points
1 parent 1463114 commit b6314c2

16 files changed

Lines changed: 395 additions & 86 deletions

.changeset/huge-mammals-give.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@endo/module-source': patch
3+
'@endo/compartment-mapper': patch
4+
---
5+
6+
Fixes type of `SourceMapHook`; differentiate it from `ParseSourceMapHook` in `@endo/compartment-mapper`.

packages/compartment-mapper/src/types/external.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
ThirdPartyStaticModuleInterface,
1313
Transform,
1414
} from 'ses';
15+
import type { SourceMapObject } from '@endo/module-source';
1516
import type {
1617
ATTENUATORS_COMPARTMENT,
1718
ENTRY_COMPARTMENT,
@@ -650,6 +651,15 @@ export type SourceMapHookDetails = {
650651
sha512: string;
651652
};
652653

654+
/**
655+
* Source map hook as received by {@link ParseFn}.
656+
*
657+
* The import hook wraps the public {@link SourceMapHook} into this shape; it
658+
* receives the raw source map object from the code generator, not a JSON
659+
* string.
660+
*/
661+
export type ParseSourceMapHook = (sourceMapObject: SourceMapObject) => void;
662+
653663
export type ModuleTransforms = Record<string, ModuleTransform>;
654664

655665
export type SyncModuleTransforms = Record<string, SyncModuleTransform>;
@@ -735,19 +745,27 @@ export interface AsyncParserImplementation extends BaseParserImplementation {
735745
synchronous: false;
736746
}
737747

738-
type ParseArguments = [
748+
/**
749+
* Options bag for a {@link ParseFn} or {@link AsyncParseFn}.
750+
*/
751+
export type ParseOptions = Partial<{
752+
sourceMap: string | undefined;
753+
sourceMapHook: ParseSourceMapHook | undefined;
754+
sourceMapUrl: string | undefined;
755+
readPowers: ReadFn | ReadPowers | undefined;
756+
compartmentDescriptor: CompartmentDescriptor | undefined;
757+
}> &
758+
ArchiveOnlyOption;
759+
760+
/**
761+
* Arguments for a {@link ParseFn} or {@link AsyncParseFn}.
762+
*/
763+
export type ParseArguments = [
739764
bytes: Uint8Array,
740765
specifier: string,
741766
moduleLocation: string,
742767
packageLocation: string,
743-
options?: Partial<{
744-
sourceMap: string | undefined;
745-
sourceMapHook: SourceMapHook | undefined;
746-
sourceMapUrl: string | undefined;
747-
readPowers: ReadFn | ReadPowers | undefined;
748-
compartmentDescriptor: CompartmentDescriptor | undefined;
749-
}> &
750-
ArchiveOnlyOption,
768+
options?: ParseOptions,
751769
];
752770

753771
/**

packages/module-source/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1+
// eslint-disable-next-line import/export
2+
export * from './src/external.types.js';
3+
14
export { ModuleSource } from './src/module-source.js';

packages/module-source/package.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@
2424
"exports": {
2525
".": {
2626
"xs": "./src-xs/index.js",
27+
"types": "./index.d.ts",
2728
"default": "./index.js"
2829
},
29-
"./shim.js": "./shim.js",
30+
"./shim.js": {
31+
"types": "./src/shim.types.d.ts",
32+
"default": "./shim.js"
33+
},
3034
"./package.json": "./package.json"
3135
},
3236
"scripts": {
@@ -51,6 +55,8 @@
5155
},
5256
"devDependencies": {
5357
"@endo/ses-ava": "workspace:^",
58+
"@types/babel__generator": "~7.27.0",
59+
"@types/babel__traverse": "~7.28.0",
5460
"ava": "catalog:dev",
5561
"babel-eslint": "^10.1.0",
5662
"benchmark": "^2.1.4",
@@ -84,6 +90,14 @@
8490
"^@endo/module-source(?:/.*)?$"
8591
]
8692
}
93+
],
94+
"jsdoc/check-tag-names": [
95+
"error",
96+
{
97+
"definedTags": [
98+
"privateRemarks"
99+
]
100+
}
87101
]
88102
},
89103
"ignorePatterns": [
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export type * from './types/visitor-passes.ts';
2+
export type {
3+
CjsModuleSourceRecord,
4+
SourceMapObject,
5+
SourceMapHook,
6+
SourceMapHookDetails,
7+
ModuleSourceOptions,
8+
} from './types/module-source.ts';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {};

packages/module-source/src/module-source.js

Lines changed: 16 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import { makeModuleAnalyzer } from './transform-analyze.js';
44

5-
const { keys, values } = Object;
5+
/**
6+
* @import {ModuleSourceOptions} from './types/module-source.js'
7+
*/
68

79
// Disable readonly markings.
810
const freeze = /** @type {<T>(v: T) => T} */ (Object.freeze);
@@ -33,28 +35,6 @@ const freeze = /** @type {<T>(v: T) => T} */ (Object.freeze);
3335

3436
const analyzeModule = makeModuleAnalyzer();
3537

36-
/**
37-
* @typedef {object} SourceMapHookDetails
38-
* @property {string} compartment
39-
* @property {string} module
40-
* @property {string} location
41-
* @property {string} sha512
42-
*/
43-
44-
/**
45-
* @callback SourceMapHook
46-
* @param {string} sourceMap
47-
* @param {SourceMapHookDetails} details
48-
*/
49-
50-
/**
51-
* @typedef {object} Options
52-
* @property {string | undefined} [sourceUrl]
53-
* @property {string | undefined} [sourceMap]
54-
* @property {string | undefined} [sourceMapUrl]
55-
* @property {SourceMapHook | undefined} [sourceMapHook]
56-
*/
57-
5838
// XXX implements import('ses').PrecompiledModuleSource but adding
5939
// `@implements` errors that this isn't a class and `@returns` errors that
6040
// there's no value returned.
@@ -64,7 +44,7 @@ const analyzeModule = makeModuleAnalyzer();
6444
*
6545
* @class
6646
* @param {string} source
67-
* @param {string | Options} [opts]
47+
* @param {string | ModuleSourceOptions} [opts]
6848
*/
6949
export function ModuleSource(source, opts = {}) {
7050
if (new.target === undefined) {
@@ -75,45 +55,18 @@ export function ModuleSource(source, opts = {}) {
7555
if (typeof opts === 'string') {
7656
opts = { sourceUrl: opts };
7757
}
78-
const {
79-
imports,
80-
functorSource,
81-
liveExportMap,
82-
reexportMap,
83-
fixedExportMap,
84-
exportAlls,
85-
needsImport,
86-
needsImportMeta,
87-
} = analyzeModule(source, opts);
88-
this.imports = freeze([...keys(imports)]);
89-
this.exports = freeze(
90-
[
91-
...keys(liveExportMap),
92-
...keys(fixedExportMap),
93-
...values(reexportMap)
94-
.flat()
95-
.map(([_, exportName]) => exportName),
96-
].sort(),
97-
);
98-
this.reexports = freeze([...exportAlls].sort());
99-
this.__syncModuleProgram__ = functorSource;
100-
for (const entry of values(liveExportMap)) {
101-
freeze(entry);
102-
}
103-
for (const entry of values(fixedExportMap)) {
104-
freeze(entry);
105-
}
106-
for (const reexports of values(reexportMap)) {
107-
for (const pair of reexports) {
108-
freeze(pair);
109-
}
110-
freeze(reexports);
111-
}
112-
this.__liveExportMap__ = freeze(liveExportMap);
113-
this.__reexportMap__ = freeze(reexportMap);
114-
this.__fixedExportMap__ = freeze(fixedExportMap);
115-
this.__needsImport__ = needsImport;
116-
this.__needsImportMeta__ = needsImportMeta;
58+
// analyzeModule now returns a frozen PrecompiledModuleSource-shaped record
59+
// via buildModuleRecord(), so we copy its properties directly.
60+
const record = analyzeModule(source, opts);
61+
this.imports = record.imports;
62+
this.exports = record.exports;
63+
this.reexports = record.reexports;
64+
this.__syncModuleProgram__ = record.__syncModuleProgram__;
65+
this.__liveExportMap__ = record.__liveExportMap__;
66+
this.__reexportMap__ = record.__reexportMap__;
67+
this.__fixedExportMap__ = record.__fixedExportMap__;
68+
this.__needsImport__ = record.__needsImport__;
69+
this.__needsImportMeta__ = record.__needsImportMeta__;
11770
freeze(this);
11871
}
11972

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Provides {@link visitorFromPlugin}
3+
*
4+
* @module
5+
*/
6+
7+
import * as babelTypes from '@babel/types';
8+
9+
/**
10+
* @import {PluginFactory} from './types/module-source.js'
11+
* @import {Visitor} from '@babel/traverse'
12+
*/
13+
14+
/**
15+
* Extracts the Babel visitor from a Babel plugin factory function.
16+
*
17+
* @param {PluginFactory} plugin A Babel plugin factory (receives `{ types }`)
18+
* @returns {Visitor}
19+
*/
20+
21+
export const visitorFromPlugin = plugin =>
22+
plugin({ types: babelTypes }).visitor;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare global {
2+
var ModuleSource: typeof import('@endo/module-source').ModuleSource;
3+
}
4+
5+
export {};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Helpers for option handling.
3+
*
4+
* @module
5+
*/
6+
7+
/**
8+
* @import {TransformSourceParams} from './types/module-source.js'
9+
*/
10+
11+
/**
12+
* Creates a fresh `sourceOptions` object with the mutable state properties
13+
* that `makeModulePlugins` populates during analysis and transform passes.
14+
*
15+
* Callers pass overrides for fields like `sourceUrl`, `sourceMap`,
16+
* `allowHidden`, etc.
17+
*
18+
* @template {object} T
19+
* @overload
20+
* @param {T} overrides
21+
* @returns {TransformSourceParams & T}
22+
*/
23+
/**
24+
* Creates a fresh `sourceOptions` object with the mutable state properties
25+
* that `makeModulePlugins` populates during analysis and transform passes.
26+
*
27+
* @overload
28+
* @returns {TransformSourceParams}
29+
*/
30+
31+
/**
32+
* Creates a fresh `sourceOptions` object with the mutable state properties
33+
* that `makeModulePlugins` populates during analysis and transform passes.
34+
*
35+
* Callers pass overrides for fields like `sourceUrl`, `sourceMap`,
36+
* `allowHidden`, etc.
37+
*
38+
* @template {object} T
39+
* @param {T} [overrides]
40+
*/
41+
export const createSourceOptions = overrides => ({
42+
sourceType: 'module',
43+
fixedExportMap: Object.create(null),
44+
imports: Object.create(null),
45+
exportAlls: [],
46+
reexportMap: Object.create(null),
47+
liveExportMap: Object.create(null),
48+
/** @type {Array<[string, boolean, string | undefined]>} */
49+
hoistedDecls: [],
50+
importSources: Object.create(null),
51+
importDecls: [],
52+
dynamicImport: { present: false },
53+
importMeta: { present: false },
54+
...(overrides ?? {}),
55+
});

0 commit comments

Comments
 (0)