@@ -13,7 +13,7 @@ use crate::const_replace::ConstReplacerVisitor;
13
13
use crate :: entry_strategy:: EntryPolicy ;
14
14
use crate :: filter_exports:: StripExportsVisitor ;
15
15
use crate :: props_destructuring:: transform_props_destructuring;
16
- use crate :: transform:: { QwikTransform , QwikTransformOptions , SegmentKind } ;
16
+ use crate :: transform:: { QwikTransform , QwikTransformOptions , Segment , SegmentKind } ;
17
17
use crate :: utils:: { Diagnostic , DiagnosticCategory , DiagnosticScope , SourceLocation } ;
18
18
use crate :: EntryStrategy ;
19
19
use path_slash:: PathExt ;
@@ -68,6 +68,7 @@ pub enum EmitMode {
68
68
Prod ,
69
69
Lib ,
70
70
Dev ,
71
+ Test ,
71
72
}
72
73
73
74
pub struct TransformCodeOptions < ' a > {
@@ -294,64 +295,57 @@ pub fn transform_code(config: TransformCodeOptions) -> Result<TransformOutput, a
294
295
// Collect import/export metadata
295
296
let mut collect = global_collect ( & program) ;
296
297
297
- transform_props_destructuring ( & mut program, & mut collect, & config. core_module ) ;
298
+ let mut qt: Option < QwikTransform < ' _ > > = None ;
299
+ let mut segments: Vec < Segment > = Vec :: new ( ) ;
298
300
299
- // Replace const values
301
+ // Don't further process library code
302
+ // It will be processed during client build
303
+ // This way no internal API usage is published
300
304
if config. mode != EmitMode :: Lib {
301
305
let is_dev = config. mode == EmitMode :: Dev ;
302
- let mut const_replacer =
303
- ConstReplacerVisitor :: new ( config. is_server , is_dev, & collect) ;
304
- program. visit_mut_with ( & mut const_replacer) ;
305
- }
306
- let mut qwik_transform = QwikTransform :: new ( QwikTransformOptions {
307
- path_data : & path_data,
308
- entry_policy : config. entry_policy ,
309
- explicit_extensions : config. explicit_extensions ,
310
- extension : extension. clone ( ) ,
311
- comments : Some ( & comments) ,
312
- global_collect : collect,
313
- scope : config. scope ,
314
- mode : config. mode ,
315
- core_module : config. core_module ,
316
- entry_strategy : config. entry_strategy ,
317
- reg_ctx_name : config. reg_ctx_name ,
318
- strip_ctx_name : config. strip_ctx_name ,
319
- strip_event_handlers : config. strip_event_handlers ,
320
- is_server : config. is_server ,
321
- cm : Lrc :: clone ( & source_map) ,
322
- } ) ;
323
306
324
- // Run main transform
325
- program = program. fold_with ( & mut qwik_transform) ;
307
+ // reconstruct destructured props for signal forwarding
308
+ transform_props_destructuring (
309
+ & mut program,
310
+ & mut collect,
311
+ & config. core_module ,
312
+ ) ;
313
+
314
+ // replace const values
315
+ if config. mode != EmitMode :: Test {
316
+ let mut const_replacer =
317
+ ConstReplacerVisitor :: new ( config. is_server , is_dev, & collect) ;
318
+ program. visit_mut_with ( & mut const_replacer) ;
319
+ }
326
320
327
- let mut treeshaker = Treeshaker :: new ( ) ;
321
+ // split into segments
322
+ let mut qwik_transform = QwikTransform :: new ( QwikTransformOptions {
323
+ path_data : & path_data,
324
+ entry_policy : config. entry_policy ,
325
+ explicit_extensions : config. explicit_extensions ,
326
+ extension : extension. clone ( ) ,
327
+ comments : Some ( & comments) ,
328
+ global_collect : collect,
329
+ scope : config. scope ,
330
+ mode : config. mode ,
331
+ core_module : config. core_module ,
332
+ entry_strategy : config. entry_strategy ,
333
+ reg_ctx_name : config. reg_ctx_name ,
334
+ strip_ctx_name : config. strip_ctx_name ,
335
+ strip_event_handlers : config. strip_event_handlers ,
336
+ is_server : config. is_server ,
337
+ cm : Lrc :: clone ( & source_map) ,
338
+ } ) ;
339
+ program = program. fold_with ( & mut qwik_transform) ;
328
340
329
- if config. minify != MinifyMode :: None {
330
- program. visit_mut_with ( & mut treeshaker. marker ) ;
341
+ let mut treeshaker = Treeshaker :: new ( ) ;
342
+ if config. minify != MinifyMode :: None {
343
+ // remove all side effects from client, step 1
344
+ if !config. is_server {
345
+ program. visit_mut_with ( & mut treeshaker. marker ) ;
346
+ }
331
347
332
- program = program. fold_with ( & mut simplify:: simplifier (
333
- unresolved_mark,
334
- simplify:: Config {
335
- dce : simplify:: dce:: Config {
336
- preserve_imports_with_side_effects : false ,
337
- ..Default :: default ( )
338
- } ,
339
- ..Default :: default ( )
340
- } ,
341
- ) ) ;
342
- }
343
- if matches ! (
344
- config. entry_strategy,
345
- EntryStrategy :: Inline | EntryStrategy :: Hoist
346
- ) {
347
- program. visit_mut_with ( & mut SideEffectVisitor :: new (
348
- & qwik_transform. options . global_collect ,
349
- & path_data,
350
- config. src_dir ,
351
- ) ) ;
352
- } else if config. minify != MinifyMode :: None && !config. is_server {
353
- program. visit_mut_with ( & mut treeshaker. cleaner ) ;
354
- if treeshaker. cleaner . did_drop {
348
+ // simplify & strip unused code
355
349
program = program. fold_with ( & mut simplify:: simplifier (
356
350
unresolved_mark,
357
351
simplify:: Config {
@@ -363,90 +357,123 @@ pub fn transform_code(config: TransformCodeOptions) -> Result<TransformOutput, a
363
357
} ,
364
358
) ) ;
365
359
}
360
+ if matches ! (
361
+ config. entry_strategy,
362
+ EntryStrategy :: Inline | EntryStrategy :: Hoist
363
+ ) {
364
+ program. visit_mut_with ( & mut SideEffectVisitor :: new (
365
+ & qwik_transform. options . global_collect ,
366
+ & path_data,
367
+ config. src_dir ,
368
+ ) ) ;
369
+ } else if config. minify != MinifyMode :: None && !config. is_server {
370
+ // remove all side effects from client, step 2
371
+ program. visit_mut_with ( & mut treeshaker. cleaner ) ;
372
+ if treeshaker. cleaner . did_drop {
373
+ program = program. fold_with ( & mut simplify:: simplifier (
374
+ unresolved_mark,
375
+ simplify:: Config {
376
+ dce : simplify:: dce:: Config {
377
+ preserve_imports_with_side_effects : false ,
378
+ ..Default :: default ( )
379
+ } ,
380
+ ..Default :: default ( )
381
+ } ,
382
+ ) ) ;
383
+ }
384
+ }
385
+ segments = qwik_transform. segments . clone ( ) ;
386
+ qt = Some ( qwik_transform) ;
366
387
}
367
388
program. visit_mut_with ( & mut hygiene_with_config ( Default :: default ( ) ) ) ;
368
389
program. visit_mut_with ( & mut fixer ( None ) ) ;
369
390
370
- let segments = qwik_transform. segments ;
371
391
let mut modules: Vec < TransformModule > = Vec :: with_capacity ( segments. len ( ) + 10 ) ;
372
392
373
393
let comments_maps = comments. clone ( ) . take_all ( ) ;
374
- for h in segments. into_iter ( ) {
375
- let is_entry = h. entry . is_none ( ) ;
376
- let path_str = h. data . path . to_string ( ) ;
377
- let path = if path_str. is_empty ( ) {
378
- path_str
379
- } else {
380
- [ & path_str, "/" ] . concat ( )
381
- } ;
382
- let segment_path = [
383
- path,
384
- [ & h. canonical_filename , "." , & h. data . extension ] . concat ( ) ,
385
- ]
386
- . concat ( ) ;
387
- let need_handle_watch =
388
- might_need_handle_watch ( & h. data . ctx_kind , & h. data . ctx_name ) ;
389
-
390
- let ( mut segment_module, comments) = new_module ( NewModuleCtx {
391
- expr : h. expr ,
392
- path : & path_data,
393
- name : & h. name ,
394
- local_idents : & h. data . local_idents ,
395
- scoped_idents : & h. data . scoped_idents ,
396
- need_transform : h. data . need_transform ,
397
- explicit_extensions : qwik_transform. options . explicit_extensions ,
398
- global : & qwik_transform. options . global_collect ,
399
- core_module : & qwik_transform. options . core_module ,
400
- need_handle_watch,
401
- leading_comments : comments_maps. 0 . clone ( ) ,
402
- trailing_comments : comments_maps. 1 . clone ( ) ,
403
- } ) ?;
404
- if config. minify != MinifyMode :: None {
405
- segment_module = segment_module. fold_with ( & mut simplify:: simplifier (
406
- unresolved_mark,
407
- simplify:: Config {
408
- dce : simplify:: dce:: Config {
409
- preserve_imports_with_side_effects : false ,
410
- ..Default :: default ( )
411
- } ,
412
- ..Default :: default ( )
413
- } ,
414
- ) ) ;
394
+ // Now process each segment
395
+ if !segments. is_empty ( ) {
396
+ let q = qt. as_ref ( ) . unwrap ( ) ;
397
+ for h in segments. into_iter ( ) {
398
+ let is_entry = h. entry . is_none ( ) ;
399
+ let path_str = h. data . path . to_string ( ) ;
400
+ let path = if path_str. is_empty ( ) {
401
+ path_str
402
+ } else {
403
+ [ & path_str, "/" ] . concat ( )
404
+ } ;
405
+ let segment_path = [
406
+ path,
407
+ [ & h. canonical_filename , "." , & h. data . extension ] . concat ( ) ,
408
+ ]
409
+ . concat ( ) ;
410
+ let need_handle_watch =
411
+ might_need_handle_watch ( & h. data . ctx_kind , & h. data . ctx_name ) ;
412
+
413
+ let ( mut segment_module, comments) = new_module ( NewModuleCtx {
414
+ expr : h. expr ,
415
+ path : & path_data,
416
+ name : & h. name ,
417
+ local_idents : & h. data . local_idents ,
418
+ scoped_idents : & h. data . scoped_idents ,
419
+ need_transform : h. data . need_transform ,
420
+ explicit_extensions : q. options . explicit_extensions ,
421
+ global : & q. options . global_collect ,
422
+ core_module : & q. options . core_module ,
423
+ need_handle_watch,
424
+ leading_comments : comments_maps. 0 . clone ( ) ,
425
+ trailing_comments : comments_maps. 1 . clone ( ) ,
426
+ } ) ?;
427
+ // we don't need to remove side effects because the optimizer only moves what's really used
428
+ if config. minify != MinifyMode :: None {
429
+ segment_module =
430
+ segment_module. fold_with ( & mut simplify:: simplifier (
431
+ unresolved_mark,
432
+ simplify:: Config {
433
+ dce : simplify:: dce:: Config {
434
+ preserve_imports_with_side_effects : false ,
435
+ ..Default :: default ( )
436
+ } ,
437
+ ..Default :: default ( )
438
+ } ,
439
+ ) ) ;
440
+ }
441
+ segment_module
442
+ . visit_mut_with ( & mut hygiene_with_config ( Default :: default ( ) ) ) ;
443
+ segment_module. visit_mut_with ( & mut fixer ( None ) ) ;
444
+
445
+ let ( code, map) = emit_source_code (
446
+ Lrc :: clone ( & source_map) ,
447
+ Some ( comments) ,
448
+ & segment_module,
449
+ config. root_dir ,
450
+ config. source_maps ,
451
+ )
452
+ . unwrap ( ) ;
453
+
454
+ modules. push ( TransformModule {
455
+ code,
456
+ map,
457
+ is_entry,
458
+ path : segment_path,
459
+ order : h. hash ,
460
+ segment : Some ( SegmentAnalysis {
461
+ origin : h. data . origin ,
462
+ name : h. name ,
463
+ entry : h. entry ,
464
+ extension : h. data . extension ,
465
+ canonical_filename : h. canonical_filename ,
466
+ path : h. data . path ,
467
+ parent : h. data . parent_segment ,
468
+ ctx_kind : h. data . ctx_kind ,
469
+ ctx_name : h. data . ctx_name ,
470
+ captures : !h. data . scoped_idents . is_empty ( ) ,
471
+ display_name : h. data . display_name ,
472
+ hash : h. data . hash ,
473
+ loc : ( h. span . lo . 0 , h. span . hi . 0 ) ,
474
+ } ) ,
475
+ } ) ;
415
476
}
416
- segment_module. visit_mut_with ( & mut hygiene_with_config ( Default :: default ( ) ) ) ;
417
- segment_module. visit_mut_with ( & mut fixer ( None ) ) ;
418
-
419
- let ( code, map) = emit_source_code (
420
- Lrc :: clone ( & source_map) ,
421
- Some ( comments) ,
422
- & segment_module,
423
- config. root_dir ,
424
- config. source_maps ,
425
- )
426
- . unwrap ( ) ;
427
-
428
- modules. push ( TransformModule {
429
- code,
430
- map,
431
- is_entry,
432
- path : segment_path,
433
- order : h. hash ,
434
- segment : Some ( SegmentAnalysis {
435
- origin : h. data . origin ,
436
- name : h. name ,
437
- entry : h. entry ,
438
- extension : h. data . extension ,
439
- canonical_filename : h. canonical_filename ,
440
- path : h. data . path ,
441
- parent : h. data . parent_segment ,
442
- ctx_kind : h. data . ctx_kind ,
443
- ctx_name : h. data . ctx_name ,
444
- captures : !h. data . scoped_idents . is_empty ( ) ,
445
- display_name : h. data . display_name ,
446
- hash : h. data . hash ,
447
- loc : ( h. span . lo . 0 , h. span . hi . 0 ) ,
448
- } ) ,
449
- } ) ;
450
477
}
451
478
452
479
let ( code, map) = match program {
0 commit comments