Skip to content

Commit e65f0a3

Browse files
committed
fix(pack): preserve updates during HMR subscription setup
1 parent a40a7a3 commit e65f0a3

18 files changed

Lines changed: 149 additions & 37 deletions

File tree

crates/pack-napi/src/pack_api/project.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use std::{
22
borrow::Cow,
33
io::Write,
44
path::PathBuf,
5-
sync::LazyLock,
5+
sync::{
6+
Arc, LazyLock,
7+
atomic::{AtomicBool, Ordering},
8+
},
69
thread::{self, JoinHandle},
710
time::{Duration, Instant},
811
};
@@ -54,7 +57,7 @@ use turbo_unix_path::get_relative_path_to;
5457
use turbopack_core::{
5558
PROJECT_FILESYSTEM_NAME, SOURCE_URL_PROTOCOL,
5659
source_map::{SourceMap, Token},
57-
version::{PartialUpdate, TotalUpdate, Update},
60+
version::{PartialUpdate, TotalUpdate, Update, Version},
5861
};
5962
use turbopack_ecmascript_hmr_protocol::{ClientUpdateInstruction, ResourceIdentifier};
6063
use turbopack_trace_utils::{
@@ -768,25 +771,43 @@ pub fn project_hmr_events(
768771
#[napi(ts_arg_type = "{ __napiType: \"Project\" }")] project: External<ProjectInstance>,
769772
identifier: RcStr,
770773
func: JsFunction,
774+
expected_version: Option<RcStr>,
771775
) -> napi::Result<External<RootTask>> {
772776
let turbopack_ctx = project.turbopack_ctx.clone();
773777
let project = project.container;
774778
let session = TransientInstance::new(());
779+
let check_expected_version = Arc::new(AtomicBool::new(expected_version.is_some()));
780+
let check_expected_version_after_emit = check_expected_version.clone();
775781
subscribe(
776782
turbopack_ctx,
777783
func,
778784
{
779785
let outer_identifier = identifier.clone();
780786
let session = session.clone();
787+
let expected_version = expected_version.clone();
788+
let check_expected_version = check_expected_version.clone();
781789
move || {
782790
let identifier: RcStr = outer_identifier.clone();
783791
let session = session.clone();
792+
let expected_version = expected_version.clone();
793+
let check_expected_version = check_expected_version.clone();
784794
async move {
785795
let project = project.project().to_resolved().await?;
786796
let state = project
787797
.hmr_version_state(identifier.clone(), session)
788798
.to_resolved()
789799
.await?;
800+
let should_check_expected_version =
801+
check_expected_version.load(Ordering::Acquire);
802+
let version_mismatch = if should_check_expected_version {
803+
if let Some(expected_version) = expected_version {
804+
state.get().id().owned().await? != expected_version
805+
} else {
806+
false
807+
}
808+
} else {
809+
false
810+
};
790811

791812
let update_op =
792813
hmr_update_with_issues_operation(project, identifier.clone(), state);
@@ -807,12 +828,17 @@ pub fn project_hmr_events(
807828
state.set(to.clone()).await?;
808829
}
809830
}
810-
Ok((Some(update.clone()), issues.clone()))
831+
Ok((
832+
Some(update.clone()),
833+
issues.clone(),
834+
version_mismatch,
835+
should_check_expected_version,
836+
))
811837
}
812838
}
813839
},
814840
move |ctx| {
815-
let (update, issues) = ctx.value;
841+
let (update, issues, version_mismatch, should_check_expected_version) = ctx.value;
816842

817843
let napi_issues = issues
818844
.iter()
@@ -828,6 +854,9 @@ pub fn project_hmr_events(
828854
headers: None,
829855
};
830856
let update = match update.as_deref() {
857+
_ if version_mismatch => {
858+
ClientUpdateInstruction::restart(&identifier, &update_issues)
859+
}
831860
None | Some(Update::Missing) | Some(Update::Total(_)) => {
832861
ClientUpdateInstruction::restart(&identifier, &update_issues)
833862
}
@@ -839,8 +868,13 @@ pub fn project_hmr_events(
839868
Some(Update::None) => ClientUpdateInstruction::issues(&identifier, &update_issues),
840869
};
841870

871+
let result = ctx.env.to_js_value(&update)?;
872+
if should_check_expected_version {
873+
check_expected_version_after_emit.store(false, Ordering::Release);
874+
}
875+
842876
Ok(vec![TurbopackResult {
843-
result: ctx.env.to_js_value(&update)?,
877+
result,
844878
issues: napi_issues,
845879
}])
846880
},
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["TURBOPACK_CHUNK_LISTS"] || (globalThis["TURBOPACK_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["input_0e1f1939.js"],
4-
source: "entry"
4+
source: "entry",
5+
version: "7rxQMXazpzA"
56
});
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["TURBOPACK_CHUNK_LISTS"] || (globalThis["TURBOPACK_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["chunks/input_message_7d12845b.dev.js","chunks/input_message_6ccb1ced.dev.js","chunks/input_index_c388c1fc.dev.js"],
4-
source: "entry"
4+
source: "entry",
5+
version: "CoSIY1jQbtg"
56
});
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["utooChunk_publicHmrApi_CHUNK_LISTS"] || (globalThis["utooChunk_publicHmrApi_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["input_hmr_64f1dfbb.js","input_hmr_b64e9d80.js","_root-of-the-server___5f8a1116.js"],
4-
source: "entry"
4+
source: "entry",
5+
version: "U8E8sDkZ0cs"
56
});
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["TURBOPACK_CHUNK_LISTS"] || (globalThis["TURBOPACK_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["input_lazy_91bce909.js","input_index_3f44269c.js"],
4-
source: "entry"
4+
source: "entry",
5+
version: "dgQ2iSodtNU"
56
});
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["TURBOPACK_CHUNK_LISTS"] || (globalThis["TURBOPACK_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["input_lazy_5395e95a.js"],
4-
source: "dynamic"
4+
source: "dynamic",
5+
version: "i0naJpmlINY"
56
});

crates/pack-tests/tests/snapshot/runtime/app_dev_runtime/output/main.js

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pack-tests/tests/snapshot/runtime/app_dev_runtime/output/main.js.map

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["TURBOPACK_CHUNK_LISTS"] || (globalThis["TURBOPACK_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["styles/input_style_b6e2d8cb.dev.css","input_index_bdf2db6d.js"],
4-
source: "entry"
4+
source: "entry",
5+
version: "UXWr2HER8+s"
56
});
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(globalThis["TURBOPACK_CHUNK_LISTS"] || (globalThis["TURBOPACK_CHUNK_LISTS"] = [])).push({
22
script: typeof document === "object" ? document.currentScript : undefined,
33
chunks: ["_project___e9ec4102.js"],
4-
source: "entry"
5-
});
4+
source: "entry",
5+
version: "GC0nxlsET5c"
6+
});

0 commit comments

Comments
 (0)