Skip to content

Commit 329a788

Browse files
authored
Merge pull request #10 from metacall/fix/async-await-compilation
Fix/async await compilation
2 parents bb1545b + b69e9bd commit 329a788

File tree

13 files changed

+125
-100
lines changed

13 files changed

+125
-100
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/metassr-build/src/bundler.rs

Whitespace-only changes.

crates/metassr-build/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
pub mod bundler;
21
pub mod client;
32
pub mod server;
43
pub(crate) mod shared;

crates/metassr-build/src/server/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ use std::{
2323
ffi::OsStr,
2424
fs,
2525
path::{Path, PathBuf},
26-
thread::sleep,
27-
time::Duration,
2826
};
2927
use targets::TargetsGenerator;
3028

@@ -88,8 +86,6 @@ impl Build for ServerSideBuilder {
8886
return Err(anyhow!("Bundling failed: {e}"));
8987
}
9088

91-
// TODO: find a solution to remove this line
92-
sleep(Duration::from_secs(1));
9389
let dist = DistDir::new(&self.dist_path)?.analyze()?;
9490

9591
let manifest =

crates/metassr-build/src/server/renderer/head.rs

+5-32
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,13 @@
11
use anyhow::{anyhow, Result};
22
use lazy_static::lazy_static;
33
use metacall::{loaders, metacall_no_arg};
4-
use metassr_utils::cache_dir::CacheDir;
5-
use std::{
6-
collections::HashMap, ffi::OsStr, path::PathBuf, sync::Mutex, thread::sleep, time::Duration,
7-
};
4+
use metassr_utils::{cache_dir::CacheDir, checker::CheckerState};
5+
use std::{collections::HashMap, ffi::OsStr, path::PathBuf, sync::Mutex};
86

97
use metassr_bundler::WebBundler;
108

119
lazy_static! {
12-
static ref IS_HEAD_SCRIPT_LOADED: Mutex<HeadSciptLoadingState> =
13-
Mutex::new(HeadSciptLoadingState::default());
14-
}
15-
16-
/// A detector for if the head is loaded or not.
17-
#[derive(Debug)]
18-
pub struct HeadSciptLoadingState(bool);
19-
20-
impl HeadSciptLoadingState {
21-
pub fn new() -> Self {
22-
Self(false)
23-
}
24-
pub fn loaded(&mut self) {
25-
self.0 = true
26-
}
27-
pub fn is_loaded(&self) -> bool {
28-
self.0
29-
}
30-
}
31-
32-
impl Default for HeadSciptLoadingState {
33-
fn default() -> Self {
34-
Self::new()
35-
}
10+
static ref IS_HEAD_SCRIPT_LOADED: Mutex<CheckerState> = Mutex::new(CheckerState::default());
3611
}
3712

3813
pub struct HeadRenderer {
@@ -53,18 +28,16 @@ impl HeadRenderer {
5328

5429
pub fn render(&mut self, bundler: bool) -> Result<String> {
5530
let mut guard = IS_HEAD_SCRIPT_LOADED.lock().unwrap();
56-
if !guard.is_loaded() {
31+
if !guard.is_true() {
5732
if bundler {
5833
self.bundle()?;
59-
// TODO: remove this line
60-
sleep(Duration::from_millis(500));
6134
}
6235

6336
let _ = loaders::from_single_file(
6437
"node",
6538
format!("{}/head.js", self.cache_dir.dir_path().display()),
6639
);
67-
guard.loaded()
40+
guard.make_true()
6841
}
6942
drop(guard);
7043

crates/metassr-bundler/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ lazy_static = "1.5.0"
1111
metacall = "0.4.1"
1212
metassr-utils = { path = "../metassr-utils" }
1313
serde_json = "1.0.128"
14+
tracing = "0.1.40"

crates/metassr-bundler/src/bundle.js

+20-27
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
const { rspack } = require('@rspack/core');
2-
const path = require("path");
2+
const path = require('path');
33

44
function safelyParseJSON(json) {
5-
let parsed
6-
75
try {
8-
parsed = JSON.parse(json)
6+
return JSON.parse(json)
97
} catch (_) {
10-
parsed = undefined
8+
return undefined
119
}
12-
13-
return parsed // Could be undefined!
1410
}
1511

1612
let config = {
1713

1814
output: {
19-
filename: "[name].js",
15+
filename: '[name].js',
2016
library: {
21-
type: "commonjs2",
17+
type: 'commonjs2',
2218
},
23-
publicPath: ""
19+
publicPath: ''
2420
},
2521
resolve: {
2622
extensions: ['.js', '.jsx', '.tsx', '.ts']
@@ -46,7 +42,7 @@ let config = {
4642
preserveAllComments: false,
4743
transform: {
4844
react: {
49-
runtime: "automatic",
45+
runtime: 'automatic',
5046
throwIfNamespace: true,
5147
useBuiltins: false,
5248
},
@@ -70,7 +66,7 @@ let config = {
7066
},
7167
transform: {
7268
react: {
73-
runtime: "automatic",
69+
runtime: 'automatic',
7470
throwIfNamespace: true,
7571
useBuiltins: false,
7672
},
@@ -89,9 +85,7 @@ let config = {
8985
}
9086
}
9187

92-
93-
94-
function web_bundling(entry, dist) {
88+
async function web_bundling(entry, dist) {
9589

9690
const compiler = rspack(
9791
{
@@ -111,19 +105,18 @@ function web_bundling(entry, dist) {
111105

112106
);
113107

114-
compiler.run((error, stats) => {
115-
if (error) {
116-
console.error(error);
117-
process.exit(2);
118-
}
119-
if (stats && stats.hasErrors()) {
120-
process.exitCode = 1;
121-
}
122-
if (!compiler || !stats) {
123-
return;
124-
}
108+
return new Promise((resolve, reject) => {
109+
return compiler.run((error, stats) => {
110+
if (error) {
111+
reject(error.message);
112+
}
113+
114+
if (error || stats?.hasErrors()) {
115+
reject(stats.toString("errors-only"));
116+
}
117+
resolve(0);
118+
});
125119
});
126-
127120
}
128121

129122
module.exports = {

crates/metassr-bundler/src/lib.rs

+63-27
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
11
use anyhow::{anyhow, Result};
22
use lazy_static::lazy_static;
3-
use metacall::{loaders, metacall, MetacallNull};
4-
use std::{collections::HashMap, ffi::OsStr, marker::Sized, path::Path, sync::Mutex};
3+
use metacall::{loaders, metacall, MetacallFuture, MetacallValue};
4+
use metassr_utils::checker::CheckerState;
5+
use std::{
6+
collections::HashMap,
7+
ffi::OsStr,
8+
marker::Sized,
9+
path::Path,
10+
sync::{Arc, Condvar, Mutex},
11+
};
12+
use tracing::error;
513

614
lazy_static! {
7-
static ref IS_BUNDLING_SCRIPT_LOADED: Mutex<BundleSciptLoadingState> =
8-
Mutex::new(BundleSciptLoadingState::new());
15+
/// A detector for if the bundling script `./bundle.js` is loaded or not. It is used to solve multiple loading script error in metacall.
16+
static ref IS_BUNDLING_SCRIPT_LOADED: Mutex<CheckerState> = Mutex::new(CheckerState::new());
17+
18+
/// A simple checker to check if the bundling function is done or not. It is used to block the program until bundling done.
19+
static ref IS_COMPLIATION_WAIT: Arc<CompilationWait> = Arc::new(CompilationWait::default());
920
}
1021
static BUILD_SCRIPT: &str = include_str!("./bundle.js");
1122
const BUNDLING_FUNC: &str = "web_bundling";
1223

13-
/// A detector for if the bundling script `./bundle.js` is loaded or not.
14-
#[derive(Debug)]
15-
pub struct BundleSciptLoadingState(bool);
16-
17-
impl BundleSciptLoadingState {
18-
pub fn new() -> Self {
19-
Self(false)
20-
}
21-
pub fn loaded(&mut self) {
22-
self.0 = true
23-
}
24-
pub fn is_loaded(&self) -> bool {
25-
self.0
26-
}
24+
/// A simple struct for compilation wait of the bundling function.
25+
struct CompilationWait {
26+
checker: Mutex<CheckerState>,
27+
cond: Condvar,
2728
}
2829

29-
impl Default for BundleSciptLoadingState {
30+
impl Default for CompilationWait {
3031
fn default() -> Self {
31-
Self::new()
32+
Self {
33+
checker: Mutex::new(CheckerState::with(false)),
34+
cond: Condvar::new(),
35+
}
3236
}
3337
}
3438

@@ -56,24 +60,56 @@ impl<'a> WebBundler<'a> {
5660
}
5761
pub fn exec(&self) -> Result<()> {
5862
let mut guard = IS_BUNDLING_SCRIPT_LOADED.lock().unwrap();
59-
if !guard.is_loaded() {
63+
if !guard.is_true() {
6064
if let Err(e) = loaders::from_memory("node", BUILD_SCRIPT) {
6165
return Err(anyhow!("Cannot load bundling script: {e:?}"));
6266
}
63-
guard.loaded();
67+
guard.make_true();
6468
}
6569
drop(guard);
66-
67-
if let Err(e) = metacall::<MetacallNull>(
70+
71+
fn resolve(_: Box<dyn MetacallValue>, _: Box<dyn MetacallValue>) {
72+
let compilation_wait = &*Arc::clone(&IS_COMPLIATION_WAIT);
73+
let mut started = compilation_wait.checker.lock().unwrap();
74+
75+
started.make_true();
76+
// We notify the condvar that the value has changed
77+
compilation_wait.cond.notify_one();
78+
}
79+
80+
fn reject(err: Box<dyn MetacallValue>, _: Box<dyn MetacallValue>) {
81+
let compilation_wait = &*Arc::clone(&IS_COMPLIATION_WAIT);
82+
let mut started = compilation_wait.checker.lock().unwrap();
83+
84+
error!("Bundling rejected: {err:?}");
85+
86+
started.make_true();
87+
// We notify the condvar that the value has changed
88+
compilation_wait.cond.notify_one();
89+
}
90+
91+
let future = metacall::<MetacallFuture>(
6892
BUNDLING_FUNC,
6993
[
7094
serde_json::to_string(&self.targets)?,
7195
self.dist_path.to_str().unwrap().to_owned(),
7296
],
73-
) {
74-
return Err(anyhow!("Cannot running {BUNDLING_FUNC}(): {e:?}"));
97+
)
98+
.unwrap();
99+
100+
future.then(resolve).catch(reject).await_fut();
101+
102+
// Wait for the thread to start up.
103+
let compilation_wait = Arc::clone(&IS_COMPLIATION_WAIT);
104+
105+
let mut started = compilation_wait.checker.lock().unwrap();
106+
107+
// Waiting till future done
108+
while !started.is_true() {
109+
started = Arc::clone(&IS_COMPLIATION_WAIT).cond.wait(started).unwrap();
75110
}
76-
111+
// Reset checker
112+
started.make_false();
77113
Ok(())
78114
}
79115
}

crates/metassr-create/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl Creator {
3333
}
3434
}
3535
pub fn generate(&self) -> Result<()> {
36-
let template = self.template.load(&self)?;
36+
let template = self.template.load(self)?;
3737
let root = PathBuf::from(&self.project_name);
3838

3939
if root.exists() {

crates/metassr-utils/src/checker.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// A simple checker state
2+
#[derive(Debug)]
3+
pub struct CheckerState(bool);
4+
impl CheckerState {
5+
pub fn new() -> Self {
6+
Self(false)
7+
}
8+
9+
pub fn with(state: bool) -> Self {
10+
Self(state)
11+
}
12+
13+
pub fn make_true(&mut self) {
14+
self.0 = true
15+
}
16+
17+
pub fn make_false(&mut self) {
18+
self.0 = false
19+
}
20+
21+
pub fn is_true(&self) -> bool {
22+
self.0
23+
}
24+
}
25+
26+
impl Default for CheckerState {
27+
fn default() -> Self {
28+
Self::new()
29+
}
30+
}

crates/metassr-utils/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod cache_dir;
2+
pub mod checker;
23
pub mod dist_analyzer;
34
pub mod rand;
45
pub mod src_analyzer;

metassr-cli/src/cli/builder.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ use metassr_build::server;
88

99
use metassr_build::{client::ClientBuilder, server::ServerSideBuilder, traits::Build};
1010

11-
use std::{
12-
thread::sleep,
13-
time::{Duration, Instant},
14-
};
11+
use std::time::Instant;
1512

1613
use tracing::{debug, error};
1714

@@ -38,8 +35,6 @@ impl Exec for Builder {
3835
return Err(anyhow!("Couldn't continue building process."));
3936
}
4037

41-
// TODO: find a solution to remove this
42-
sleep(Duration::from_secs(1));
4338

4439
if let Err(e) = ServerSideBuilder::new("", &self.out_dir, self._type.into())?.build() {
4540
error!(

metassr-cli/src/cli/creator.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clap::ValueEnum;
2-
use metassr_create;
2+
use metassr_create::Creator as MetassrCreator;
33
use std::{fmt::Display, str::FromStr};
44
use tracing::{error, info};
55

@@ -30,7 +30,7 @@ impl Creator {
3030

3131
impl Exec for Creator {
3232
fn exec(&self) -> anyhow::Result<()> {
33-
match metassr_create::Creator::new(
33+
match MetassrCreator::new(
3434
&self.project_name,
3535
&self.version,
3636
&self.description,

0 commit comments

Comments
 (0)