Skip to main content

vize_bundler_before_observer/
vize_bundler_before_observer.rs

1//! Source-only whole before observations; this never rewrites a test expectation.
2mod vize_bundler_before;
3
4use lightningcss::{
5  bundler::Bundler,
6  css_modules::{Config, Pattern},
7  error::Error,
8  printer::PrinterOptions,
9  stylesheet::{MinifyOptions, ParserOptions},
10};
11use parcel_sourcemap::SourceMap;
12use serde_json::{json, Value};
13use std::{fmt, fs, path::Path};
14use vize_bundler_before::Provider;
15
16fn error<T: fmt::Debug + fmt::Display>(stage: &str, value: Error<T>) -> Value {
17  json!({"stage": stage, "display": value.to_string(), "kind": format!("{:?}", value.kind), "loc": value.loc})
18}
19
20fn observe(case: &Value, provider: &Provider) -> Value {
21  let mut map = SourceMap::new("/");
22  let options = ParserOptions {
23    css_modules: case["cssModules"].as_bool().unwrap_or(false).then(|| Config {
24      dashed_idents: true,
25      pattern: Pattern::parse("[hash]_[local]").unwrap(),
26      ..Default::default()
27    }),
28    ..Default::default()
29  };
30  let mut bundler = Bundler::new(provider, Some(&mut map), options);
31  let result = match bundler.bundle(Path::new(case["entry"].as_str().unwrap())) {
32    Ok(mut stylesheet) => {
33      // Preserve pre-minification source/map/comment/context metadata too.
34      let bundle = json!({
35        "ast": stylesheet,
36        "sources": stylesheet.sources,
37        "sourceMapUrls": stylesheet.source_map_urls,
38        "licenseComments": stylesheet.license_comments,
39        "privateContentHashesObserved": false,
40      });
41      let minify_error = if case["minify"].as_bool().unwrap_or(false) {
42        stylesheet.minify(MinifyOptions::default()).err()
43      } else {
44        None
45      };
46      if let Some(value) = minify_error {
47        json!({"bundle": bundle, "error": error("minify", value)})
48      } else {
49        match stylesheet.to_css(PrinterOptions {
50          source_map: Some(&mut map),
51          ..Default::default()
52        }) {
53          Ok(result) => json!({
54            "bundle": bundle, "code": result.code, "exports": result.exports,
55            "references": result.references, "dependencies": result.dependencies,
56          }),
57          Err(value) => json!({"bundle": bundle, "error": error("print", value)}),
58        }
59      }
60    }
61    Err(value) => json!({"error": error("bundle", value)}),
62  };
63  let mappings: Vec<Value> = map
64    .get_mappings()
65    .iter()
66    .map(|mapping| {
67      json!({
68        "generatedLine": mapping.generated_line,
69        "generatedColumn": mapping.generated_column,
70        "original": mapping.original.map(|value| json!({
71          "line": value.original_line, "column": value.original_column,
72          "source": value.source, "name": value.name,
73        })),
74      })
75    })
76    .collect();
77  json!({
78    "result": result,
79    "map": {"json": map.to_json(None).unwrap(), "sources": map.get_sources(),
80      "sourcesContent": map.get_sources_content(), "names": map.get_names(), "mappings": mappings},
81  })
82}
83
84fn main() {
85  let args: Vec<String> = std::env::args().collect();
86  assert_eq!(args.len(), 5, "manifest case pool output-directory");
87  let manifest: Value = serde_json::from_slice(&fs::read(&args[1]).unwrap()).unwrap();
88  let case = manifest["cases"]
89    .as_array()
90    .unwrap()
91    .iter()
92    .find(|case| case["id"].as_str() == Some(args[2].as_str()))
93    .unwrap();
94  let threads: usize = args[3].parse().unwrap();
95  assert!([1, 8, 32].contains(&threads));
96  let directory = Path::new(&args[4]);
97  fs::create_dir_all(directory).unwrap();
98  fs::write(
99    directory.join("startup.json"),
100    serde_json::to_vec_pretty(&json!({
101      "case": case, "threads": threads, "pid": std::process::id(),
102      "sourceRevision": std::env::var("CSS_ENGINE_SOURCE_REVISION").unwrap(),
103      "expectationsRecaptured": false, "publicationQualification": false,
104    }))
105    .unwrap(),
106  )
107  .unwrap();
108  let provider = Provider::new(case, threads, directory.join("events.jsonl"));
109  let pool = rayon::ThreadPoolBuilder::new().num_threads(threads).build().unwrap();
110  let observed = pool.install(|| observe(case, &provider));
111  fs::write(
112    directory.join("observation.json"),
113    serde_json::to_vec_pretty(&observed).unwrap(),
114  )
115  .unwrap();
116  println!("{}", serde_json::to_string(&observed).unwrap());
117}