1use swc_core::{
2 atoms::Atom,
3 common::Span,
4 ecma::ast::{
5 AssignExpr, AwaitExpr, BinExpr, CallExpr, ClassMember, CondExpr, Expr, ForOfStmt, Ident,
6 IfStmt, ImportDecl, MemberExpr, ModuleDecl, NewExpr, OptChainExpr, Program, ThisExpr,
7 UnaryExpr, VarDeclarator,
8 },
9};
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12#[repr(u8)]
13pub enum JavascriptParserPluginHook {
14 PreStatement,
15 BlockPreStatement,
16 TopLevelAwaitExpr,
17 TopLevelForOfAwaitStmt,
18 CanRename,
19 Rename,
20 Program,
21 Statement,
22 UnusedStatement,
23 ModuleDeclaration,
24 BlockPreModuleDeclaration,
25 PreDeclarator,
26 Evaluate,
27 EvaluateTypeof,
28 EvaluateCallExpression,
29 EvaluateCallExpressionMember,
30 EvaluateIdentifier,
31 CanCollectDestructuringAssignmentProperties,
32 Pattern,
33 Call,
34 CallMemberChain,
35 Member,
36 MemberChain,
37 UnhandledExpressionMemberChain,
38 MemberChainOfCallMemberChain,
39 CallMemberChainOfCallMemberChain,
40 Typeof,
41 ExpressionLogicalOperator,
42 BinaryExpression,
43 StatementIf,
44 ClassExtendsExpression,
45 ClassBodyElement,
46 ClassBodyValue,
47 Declarator,
48 NewExpression,
49 Identifier,
50 This,
51 Assign,
52 AssignMemberChain,
53 ImportCall,
54 MetaProperty,
55 Import,
56 ImportSpecifier,
57 ExportImport,
58 Export,
59 ExportImportSpecifier,
60 ExportSpecifier,
61 ExportExpression,
62 OptionalChaining,
63 ExpressionConditionalOperation,
64 Finish,
65 IsPure,
66 ImportMetaPropertyInDestructuring,
67}
68
69impl JavascriptParserPluginHook {
70 pub const COUNT: usize = Self::ImportMetaPropertyInDestructuring as usize + 1;
71
72 pub const ALL: [Self; Self::COUNT] = [
73 Self::PreStatement,
74 Self::BlockPreStatement,
75 Self::TopLevelAwaitExpr,
76 Self::TopLevelForOfAwaitStmt,
77 Self::CanRename,
78 Self::Rename,
79 Self::Program,
80 Self::Statement,
81 Self::UnusedStatement,
82 Self::ModuleDeclaration,
83 Self::BlockPreModuleDeclaration,
84 Self::PreDeclarator,
85 Self::Evaluate,
86 Self::EvaluateTypeof,
87 Self::EvaluateCallExpression,
88 Self::EvaluateCallExpressionMember,
89 Self::EvaluateIdentifier,
90 Self::CanCollectDestructuringAssignmentProperties,
91 Self::Pattern,
92 Self::Call,
93 Self::CallMemberChain,
94 Self::Member,
95 Self::MemberChain,
96 Self::UnhandledExpressionMemberChain,
97 Self::MemberChainOfCallMemberChain,
98 Self::CallMemberChainOfCallMemberChain,
99 Self::Typeof,
100 Self::ExpressionLogicalOperator,
101 Self::BinaryExpression,
102 Self::StatementIf,
103 Self::ClassExtendsExpression,
104 Self::ClassBodyElement,
105 Self::ClassBodyValue,
106 Self::Declarator,
107 Self::NewExpression,
108 Self::Identifier,
109 Self::This,
110 Self::Assign,
111 Self::AssignMemberChain,
112 Self::ImportCall,
113 Self::MetaProperty,
114 Self::Import,
115 Self::ImportSpecifier,
116 Self::ExportImport,
117 Self::Export,
118 Self::ExportImportSpecifier,
119 Self::ExportSpecifier,
120 Self::ExportExpression,
121 Self::OptionalChaining,
122 Self::ExpressionConditionalOperation,
123 Self::Finish,
124 Self::IsPure,
125 Self::ImportMetaPropertyInDestructuring,
126 ];
127
128 pub const fn mask(self) -> u64 {
129 1u64 << (self as u8)
130 }
131}
132
133const _: () = assert!(
134 JavascriptParserPluginHook::COUNT <= 64,
135 "The number of JavascriptParserPluginHook variants exceeds 64, which cannot be safely stored in a u64 bitmask."
136);
137
138#[derive(Clone, Copy, Debug, PartialEq, Eq)]
139pub struct JavascriptParserPluginHooks(u64);
140
141impl JavascriptParserPluginHooks {
142 pub const fn empty() -> Self {
143 Self(0)
144 }
145
146 pub const fn all() -> Self {
147 Self(u64::MAX)
148 }
149
150 pub const fn contains(self, hook: JavascriptParserPluginHook) -> bool {
151 self.0 & hook.mask() != 0
152 }
153
154 pub const fn with(self, hook: JavascriptParserPluginHook) -> Self {
155 Self(self.0 | hook.mask())
156 }
157}
158
159use crate::{
160 utils::eval::BasicEvaluatedExpression,
161 visitors::{
162 ClassDeclOrExpr, DestructuringAssignmentProperty, ExportDefaultDeclaration,
163 ExportDefaultExpression, ExportImport, ExportLocal, ExportedVariableInfo, JavascriptParser,
164 Statement, VariableDeclaration,
165 },
166};
167
168type KeepRight = bool;
169
170pub trait JavascriptParserPlugin {
171 fn implemented_hooks(&self) -> JavascriptParserPluginHooks {
196 if cfg!(debug_assertions) {
200 panic!(
201 "`implemented_hooks` must be generated by the `implemented_javascript_parser_hooks` macro (attribute). \
202Please annotate your `impl JavascriptParserPlugin for ...` block with `#[rspack_plugin_javascript::implemented_javascript_parser_hooks]` \
203(or `#[rspack_macros::implemented_javascript_parser_hooks]` inside the repository)."
204 );
205 }
206
207 JavascriptParserPluginHooks::all()
209 }
210
211 fn pre_statement(&self, _parser: &mut JavascriptParser, _stmt: Statement) -> Option<bool> {
216 None
217 }
218
219 fn block_pre_statement(&self, _parser: &mut JavascriptParser, _stmt: Statement) -> Option<bool> {
220 None
221 }
222
223 fn top_level_await_expr(&self, _parser: &mut JavascriptParser, _expr: &AwaitExpr) {}
225
226 fn top_level_for_of_await_stmt(&self, _parser: &mut JavascriptParser, _stmt: &ForOfStmt) {}
228
229 fn can_rename(&self, _parser: &mut JavascriptParser, _str: &str) -> Option<bool> {
230 None
231 }
232
233 fn rename(&self, _parser: &mut JavascriptParser, _expr: &Expr, _str: &str) -> Option<bool> {
234 None
235 }
236
237 fn program(&self, _parser: &mut JavascriptParser, _ast: &Program) -> Option<bool> {
238 None
239 }
240
241 fn statement(&self, _parser: &mut JavascriptParser, _stmt: Statement) -> Option<bool> {
242 None
243 }
244
245 fn unused_statement(&self, _parser: &mut JavascriptParser, _stmt: Statement) -> Option<bool> {
253 None
254 }
255
256 fn module_declaration(&self, _parser: &mut JavascriptParser, _decl: &ModuleDecl) -> Option<bool> {
257 None
258 }
259
260 fn block_pre_module_declaration(
266 &self,
267 _parser: &mut JavascriptParser,
268 _decl: &ModuleDecl,
269 ) -> Option<bool> {
270 None
271 }
272
273 fn pre_declarator(
274 &self,
275 _parser: &mut JavascriptParser,
276 _declarator: &VarDeclarator,
277 _declaration: VariableDeclaration<'_>,
278 ) -> Option<bool> {
279 None
280 }
281
282 fn evaluate<'a>(
283 &self,
284 _parser: &mut JavascriptParser,
285 _expr: &'a Expr,
286 ) -> Option<BasicEvaluatedExpression<'a>> {
287 None
288 }
289
290 fn evaluate_typeof<'a>(
291 &self,
292 _parser: &mut JavascriptParser,
293 _expr: &'a UnaryExpr,
294 _for_name: &str,
295 ) -> Option<BasicEvaluatedExpression<'a>> {
296 None
297 }
298
299 fn evaluate_identifier(
300 &self,
301 _parser: &mut JavascriptParser,
302 _for_name: &str,
303 _start: u32,
304 _end: u32,
305 ) -> Option<BasicEvaluatedExpression<'static>> {
306 None
307 }
308
309 fn evaluate_call_expression<'a>(
312 &self,
313 _parser: &mut JavascriptParser,
314 _name: &str,
315 _expr: &'a CallExpr,
316 ) -> Option<BasicEvaluatedExpression<'a>> {
317 None
318 }
319
320 fn evaluate_call_expression_member<'a>(
321 &self,
322 _parser: &mut JavascriptParser,
323 _property: &str,
324 _expr: &'a CallExpr,
325 _param: BasicEvaluatedExpression<'a>,
326 ) -> Option<BasicEvaluatedExpression<'a>> {
327 None
328 }
329
330 fn can_collect_destructuring_assignment_properties(
331 &self,
332 _parser: &mut JavascriptParser,
333 _expr: &Expr,
334 ) -> Option<bool> {
335 None
336 }
337
338 fn pattern(
339 &self,
340 _parser: &mut JavascriptParser,
341 _ident: &Ident,
342 _for_name: &str,
343 ) -> Option<bool> {
344 None
345 }
346
347 fn call(
348 &self,
349 _parser: &mut JavascriptParser,
350 _expr: &CallExpr,
351 _for_name: &str,
352 ) -> Option<bool> {
353 None
354 }
355
356 fn call_member_chain(
357 &self,
358 _parser: &mut JavascriptParser,
359 _expr: &CallExpr,
360 _for_name: &str,
361 _members: &[Atom],
362 _members_optionals: &[bool],
363 _member_ranges: &[Span],
364 ) -> Option<bool> {
365 None
366 }
367
368 fn member(
369 &self,
370 _parser: &mut JavascriptParser,
371 _expr: &MemberExpr,
372 _for_name: &str,
373 ) -> Option<bool> {
374 None
375 }
376
377 fn member_chain(
378 &self,
379 _parser: &mut JavascriptParser,
380 _expr: &MemberExpr,
381 _for_name: &str,
382 _members: &[Atom],
383 _members_optionals: &[bool],
384 _member_ranges: &[Span],
385 ) -> Option<bool> {
386 None
387 }
388
389 fn unhandled_expression_member_chain(
390 &self,
391 _parser: &mut JavascriptParser,
392 _root_info: &ExportedVariableInfo,
393 _expr: &MemberExpr,
394 ) -> Option<bool> {
395 None
396 }
397
398 #[allow(clippy::too_many_arguments)]
399 fn member_chain_of_call_member_chain(
400 &self,
401 _parser: &mut JavascriptParser,
402 _member_expr: &MemberExpr,
403 _callee_members: &[Atom],
404 _call_expr: &CallExpr,
405 _members: &[Atom],
406 _member_ranges: &[Span],
407 _for_name: &str,
408 ) -> Option<bool> {
409 None
410 }
411
412 #[allow(clippy::too_many_arguments)]
413 fn call_member_chain_of_call_member_chain(
414 &self,
415 _parser: &mut JavascriptParser,
416 _call_expr: &CallExpr,
417 _callee_members: &[Atom],
418 _inner_call_expr: &CallExpr,
419 _members: &[Atom],
420 _member_ranges: &[Span],
421 _for_name: &str,
422 ) -> Option<bool> {
423 None
424 }
425
426 fn r#typeof(
427 &self,
428 _parser: &mut JavascriptParser,
429 _expr: &UnaryExpr,
430 _for_name: &str,
431 ) -> Option<bool> {
432 None
433 }
434
435 fn expression_logical_operator(
440 &self,
441 _parser: &mut JavascriptParser,
442 _expr: &BinExpr,
443 ) -> Option<KeepRight> {
444 None
445 }
446
447 fn binary_expression(&self, _parser: &mut JavascriptParser, _expr: &BinExpr) -> Option<bool> {
450 None
451 }
452
453 fn statement_if(&self, _parser: &mut JavascriptParser, _expr: &IfStmt) -> Option<bool> {
458 None
459 }
460
461 fn class_extends_expression(
462 &self,
463 _parser: &mut JavascriptParser,
464 _super_class: &Expr,
465 _class_decl_or_expr: ClassDeclOrExpr,
466 ) -> Option<bool> {
467 None
468 }
469
470 fn class_body_element(
471 &self,
472 _parser: &mut JavascriptParser,
473 _element: &ClassMember,
474 _class_decl_or_expr: ClassDeclOrExpr,
475 ) -> Option<bool> {
476 None
477 }
478
479 fn class_body_value(
480 &self,
481 _parser: &mut JavascriptParser,
482 _element: &swc_core::ecma::ast::ClassMember,
483 _expr_span: Span,
484 _class_decl_or_expr: ClassDeclOrExpr,
485 ) -> Option<bool> {
486 None
487 }
488
489 fn declarator(
490 &self,
491 _parser: &mut JavascriptParser,
492 _expr: &VarDeclarator,
493 _stmt: VariableDeclaration<'_>,
494 ) -> Option<bool> {
495 None
496 }
497
498 fn new_expression(
499 &self,
500 _parser: &mut JavascriptParser,
501 _expr: &NewExpr,
502 _for_name: &str,
503 ) -> Option<bool> {
504 None
505 }
506
507 fn identifier(
508 &self,
509 _parser: &mut JavascriptParser,
510 _ident: &Ident,
511 _for_name: &str,
512 ) -> Option<bool> {
513 None
514 }
515
516 fn this(
517 &self,
518 _parser: &mut JavascriptParser,
519 _expr: &ThisExpr,
520 _for_name: &str,
521 ) -> Option<bool> {
522 None
523 }
524
525 fn assign(
526 &self,
527 _parser: &mut JavascriptParser,
528 _expr: &AssignExpr,
529 _for_name: &str,
530 ) -> Option<bool> {
531 None
532 }
533
534 fn assign_member_chain(
535 &self,
536 _parser: &mut JavascriptParser,
537 _expr: &AssignExpr,
538 _members: &[Atom],
539 _for_name: &str,
540 ) -> Option<bool> {
541 None
542 }
543
544 fn import_call(
545 &self,
546 _parser: &mut JavascriptParser,
547 _expr: &CallExpr,
548 _import_then: Option<&CallExpr>,
549 _members: Option<(&[Atom], bool)>,
550 ) -> Option<bool> {
551 None
552 }
553
554 fn meta_property(
555 &self,
556 _parser: &mut JavascriptParser,
557 _root_name: &Atom,
558 _span: Span,
559 ) -> Option<bool> {
560 None
561 }
562
563 fn import(
564 &self,
565 _parser: &mut JavascriptParser,
566 _statement: &ImportDecl,
567 _source: &str,
568 ) -> Option<bool> {
569 None
570 }
571
572 fn import_specifier(
573 &self,
574 _parser: &mut JavascriptParser,
575 _statement: &ImportDecl,
576 _source: &Atom,
577 _export_name: Option<&Atom>,
578 _identifier_name: &Atom,
579 ) -> Option<bool> {
580 None
581 }
582
583 fn export_import(
584 &self,
585 _parser: &mut JavascriptParser,
586 _statement: ExportImport,
587 _source: &Atom,
588 ) -> Option<bool> {
589 None
590 }
591
592 fn export(&self, _parser: &mut JavascriptParser, _statement: ExportLocal) -> Option<bool> {
593 None
594 }
595
596 fn export_import_specifier(
597 &self,
598 _parser: &mut JavascriptParser,
599 _statement: ExportImport,
600 _source: &Atom,
601 _local_id: Option<&Atom>,
602 _export_name: Option<&Atom>,
603 _export_name_span: Option<Span>,
604 ) -> Option<bool> {
605 None
606 }
607
608 fn export_specifier(
609 &self,
610 _parser: &mut JavascriptParser,
611 _statement: ExportLocal,
612 _local_id: &Atom,
613 _export_name: &Atom,
614 _export_name_span: Span,
615 ) -> Option<bool> {
616 None
617 }
618
619 fn export_expression(
620 &self,
621 _parser: &mut JavascriptParser,
622 _statement: ExportDefaultDeclaration,
623 _expr: ExportDefaultExpression,
624 ) -> Option<bool> {
625 None
626 }
627
628 fn optional_chaining(
629 &self,
630 _parser: &mut JavascriptParser,
631 _expr: &OptChainExpr,
632 ) -> Option<bool> {
633 None
634 }
635
636 fn expression_conditional_operation(
637 &self,
638 _parser: &mut JavascriptParser,
639 _expr: &CondExpr,
640 ) -> Option<bool> {
641 None
642 }
643
644 fn finish(&self, _parser: &mut JavascriptParser) -> Option<bool> {
645 None
646 }
647
648 fn is_pure(&self, _parser: &mut JavascriptParser, _expr: &Expr) -> Option<bool> {
649 None
650 }
651
652 fn import_meta_property_in_destructuring(
659 &self,
660 _parser: &mut JavascriptParser,
661 _property: &DestructuringAssignmentProperty,
662 ) -> Option<String> {
663 None
664 }
665}
666
667pub type BoxJavascriptParserPlugin = Box<dyn JavascriptParserPlugin + Send + Sync>;