Skip to content

Commit b7addca

Browse files
committed
feat(module-source): expose AST-based CJS parser
Exposes AST-based parser for CJS, as well as an `analyzeCjs` function from the `analyzer.js` subpath export. `CjsModuleSource` is also exported from the main entry point.
1 parent fdc4087 commit b7addca

16 files changed

Lines changed: 2450 additions & 0 deletions

.changeset/open-mammals-scream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@endo/module-source': minor
3+
---
4+
5+
Exposes AST-based parser for CJS, as well as an `analyzeCjs` function from the `analyzer.js` subpath export.

packages/module-source/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ That is, the XS native `bindings` will be translated to `imports`, `exports`,
8383
and `reexports` getters.
8484
This form of `ModuleSource` ignores all options.
8585

86+
## CommonJS-Specific Variant
87+
88+
In the default/Node variant of `@endo/module-source`, a `CjsModuleSource`
89+
constructor provides a similar interface for CommonJS modules. It accepts the
90+
same options as `ModuleSource` and produces a `CjsModuleSourceRecord` object
91+
containing the analysis data plus a pre-built functor source string.
92+
93+
Note: the `xs` condition currently provides only `ModuleSource`;
94+
`CjsModuleSource` is not available under `xs`.
95+
8696
## Bug Disclosure
8797

8898
Please help us practice coordinated security bug disclosure, by using the

packages/module-source/analyzer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
export * from './src/external.types.js';
33

44
export { analyzeModule } from './src/analyzer.js';
5+
export { analyzeCjs } from './src/cjs-analyzer.js';

packages/module-source/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
export * from './src/external.types.js';
33

44
export { ModuleSource } from './src/module-source.js';
5+
export { CjsModuleSource } from './src/cjs-module-source.js';
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Low-level module analysis primitives for CJS.
3+
*
4+
* {@link analyzeCjs} returns a per-parse context object
5+
* holding plain `{ visitor }` objects and a `buildRecord` function.
6+
*
7+
* Consumers are responsible for:
8+
* 1. Traversing the AST with `ctx.analyzePass.visitor`.
9+
* 2. Traversing the (mutated) AST with `ctx.transformPass.visitor`.
10+
* 3. Generating code.
11+
* 4. Calling `ctx.buildRecord(code, location)` to produce the module record.
12+
*
13+
* @module
14+
*/
15+
16+
import makeCjsModulePlugins from './cjs-babel-plugin.js';
17+
import { buildCjsFunctorSource, buildCjsModuleRecord } from './cjs-functor.js';
18+
import { createCjsSourceOptions } from './source-options.js';
19+
20+
/**
21+
* @import {AnalysisOptions} from './types/analyzer.js'
22+
* @import {CjsAnalysisContext} from './types/cjs-analyzer.js'
23+
*/
24+
25+
/**
26+
* Creates a fresh CJS analysis context for a single module parse.
27+
*
28+
* @param {AnalysisOptions} [options]
29+
* @returns {CjsAnalysisContext}
30+
*/
31+
32+
export const analyzeCjs = (options = {}) => {
33+
const { allowHidden = false } = options;
34+
const sourceOptions = createCjsSourceOptions({ allowHidden });
35+
const { analyzePlugin, transformPlugin } =
36+
makeCjsModulePlugins(sourceOptions);
37+
38+
return {
39+
analyzePass: analyzePlugin,
40+
transformPass: transformPlugin,
41+
42+
buildRecord(generatedCode, location) {
43+
const functorSource = buildCjsFunctorSource(
44+
generatedCode,
45+
sourceOptions,
46+
location,
47+
);
48+
return buildCjsModuleRecord(sourceOptions, functorSource);
49+
},
50+
};
51+
};

0 commit comments

Comments
 (0)