@@ -17,11 +17,14 @@ import {
1717 SourceFile ,
1818 type SourceFlags
1919} from "./SourceFile.js" ;
20- import { isOneLineExpressionExport } from "./utils/index.js" ;
2120import { JsSourceParser , type SourceParser } from "./JsSourceParser.js" ;
2221import { ProbeRunner , type Probe } from "./ProbeRunner.js" ;
2322import { walkEnter } from "./walker/index.js" ;
2423import * as trojan from "./obfuscators/trojan-source.js" ;
24+ import {
25+ isOneLineExpressionExport
26+ } from "./utils/index.js" ;
27+ import type { Pipeline } from "./pipelines/pipeline.js" ;
2528
2629export interface Dependency {
2730 unsafe : boolean ;
@@ -85,6 +88,7 @@ export interface AstAnalyserOptions {
8588 * @default false
8689 */
8790 optionalWarnings ?: boolean | Iterable < OptionalWarningName > ;
91+ pipelines ?: Pipeline [ ] ;
8892}
8993
9094export interface PrepareSourceOptions {
@@ -94,14 +98,17 @@ export interface PrepareSourceOptions {
9498export class AstAnalyser {
9599 parser : SourceParser ;
96100 probes : Probe [ ] ;
101+ pipelines : Pipeline [ ] = [ ] ;
97102
98103 constructor ( options : AstAnalyserOptions = { } ) {
99104 const {
100105 customProbes = [ ] ,
101106 optionalWarnings = false ,
102- skipDefaultProbes = false
107+ skipDefaultProbes = false ,
108+ pipelines = [ ]
103109 } = options ;
104110
111+ this . pipelines = pipelines ;
105112 this . parser = options . customParser ?? new JsSourceParser ( ) ;
106113
107114 let probes = ProbeRunner . Defaults ;
@@ -129,6 +136,24 @@ export class AstAnalyser {
129136 this . probes = probes ;
130137 }
131138
139+ #runPipelines(
140+ body : ESTree . Program [ "body" ]
141+ ) : ESTree . Program [ "body" ] {
142+ const runnedPipelines = new Set < string > ( ) ;
143+ let updatedBody = body ;
144+
145+ for ( const pipeline of this . pipelines ) {
146+ if ( runnedPipelines . has ( pipeline . name ) ) {
147+ continue ;
148+ }
149+
150+ updatedBody = pipeline . walk ( updatedBody ) ;
151+ runnedPipelines . add ( pipeline . name ) ;
152+ }
153+
154+ return updatedBody ;
155+ }
156+
132157 analyse (
133158 str : string ,
134159 options : RuntimeOptions = { }
@@ -144,6 +169,8 @@ export class AstAnalyser {
144169 const body = this . parser . parse ( this . prepareSource ( str , { removeHTMLComments } ) , {
145170 isEcmaScriptModule : Boolean ( module )
146171 } ) ;
172+
173+ const updatedBody = this . #runPipelines( body ) ;
147174 const source = new SourceFile ( ) ;
148175 if ( trojan . verify ( str ) ) {
149176 source . warnings . push (
@@ -161,7 +188,7 @@ export class AstAnalyser {
161188 }
162189
163190 // we walk each AST Nodes, this is a purely synchronous I/O
164- walkEnter ( body , function walk ( node ) {
191+ walkEnter ( updatedBody , function walk ( node ) {
165192 // Skip the root of the AST.
166193 if ( Array . isArray ( node ) ) {
167194 return ;
0 commit comments