Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
c4d3c04
feat(mf): support layered container exposes
ScriptedAlchemy Jul 22, 2026
b3a3fed
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Jul 27, 2026
c0f445d
Merge commit '2a348f967f' into codex/work-pr14912
ScriptedAlchemy Jul 27, 2026
f16f215
Merge commit 'e0a975ff10' into codex/work-pr14912
ScriptedAlchemy Jul 27, 2026
7ee5128
Merge commit '223f6e860f' into codex/work-pr14912
ScriptedAlchemy Jul 27, 2026
6c1af2c
Merge commit '3e4af0cb5f' into codex/work-pr14912
ScriptedAlchemy Jul 27, 2026
1c3eb05
perf(mf): use unstable sorts for deterministic strings
ScriptedAlchemy Jul 27, 2026
bce2884
perf(mf): patch shared exports without typed stats
ScriptedAlchemy Jul 27, 2026
53b1f7e
perf(mf): compact optional exposed layers
ScriptedAlchemy Jul 27, 2026
b21cf1d
Merge commit '9392c3bb75' into codex/work-pr14912
ScriptedAlchemy Jul 28, 2026
b1722dc
Merge commit 'ffd6b71541' into codex/work-pr14912
ScriptedAlchemy Jul 28, 2026
4f1eef5
Merge commit '72c9492ee4' into codex/work-pr14912
ScriptedAlchemy Jul 28, 2026
27771aa
Merge commit 'cbaca67ee4' into codex/work-pr14912
ScriptedAlchemy Jul 28, 2026
9c461fa
Merge commit 'fefd61d32e' into codex/work-pr14912
ScriptedAlchemy Jul 28, 2026
84a127a
Merge commit '2119bde04f' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
2476c02
Merge commit '2c0d2b7210' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
1a74f7d
fix(mf): preserve layered option compatibility
ScriptedAlchemy Jul 29, 2026
c20131b
Merge commit '982bd52e2c' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
aa1d9ec
Merge commit '46a22cb771' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
f592033
Merge commit 'd540607a38' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
668cfee
fix(mf): preserve expose option compatibility
ScriptedAlchemy Jul 29, 2026
1326aca
fix(mf): preserve v1 option extensibility
ScriptedAlchemy Jul 29, 2026
bfa3a15
Merge commit '4aad05beae' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
ef0f210
Merge commit '1656d1bec8' into codex/work-pr14912
ScriptedAlchemy Jul 29, 2026
3dee67e
fix(mf): preserve container option extensibility
ScriptedAlchemy Jul 29, 2026
a45c54d
fix(mf): retain exposed dependency constructor
ScriptedAlchemy Jul 29, 2026
11e4a2f
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Jul 29, 2026
aecfa8e
fix(mf): export enhanced container options
ScriptedAlchemy Jul 29, 2026
04c9206
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Jul 29, 2026
cabc390
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 7, 2026
c7a248b
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 8, 2026
bfe4fa5
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 8, 2026
ace9d2e
test(mf): check the legacy expose constructor signature without const…
ScriptedAlchemy Sep 8, 2026
e07cb23
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 8, 2026
22d1a17
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 8, 2026
789d856
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 8, 2026
b108343
fix(mf): carry expose layers inside the container identifier payload
ScriptedAlchemy Sep 8, 2026
7a95005
Merge remote-tracking branch 'origin/codex/mf-share-scope-runtime' in…
ScriptedAlchemy Sep 8, 2026
533028a
docs(mf): explain and exercise expose layers
ScriptedAlchemy Sep 8, 2026
089b02c
Merge refreshed shared runtime into layered exposes
ScriptedAlchemy Sep 8, 2026
e8b02d0
Merge branch 'codex/work-pr14911' into codex/work-pr14912
ScriptedAlchemy Sep 8, 2026
73c90ee
test(mf): cover layered exposes through config cases
ScriptedAlchemy Sep 8, 2026
5cee2d5
Merge branch 'codex/work-pr14911' into codex/work-pr14912
ScriptedAlchemy Sep 8, 2026
4b9a1e2
fix(mf): retain container hooks after test cleanup
ScriptedAlchemy Sep 8, 2026
d1d45c6
Merge branch 'codex/work-pr14911' into codex/work-pr14912
ScriptedAlchemy Sep 8, 2026
b3ca943
Merge branch 'codex/work-pr14911' into codex/work-pr14912
ScriptedAlchemy Sep 8, 2026
60e794b
refactor(mf): remove redundant expose layer truncation
ScriptedAlchemy Sep 9, 2026
0454b2f
chore: sync layered exposes with runtime base
ScriptedAlchemy Sep 9, 2026
f979f70
chore: sync layered exposes with runtime base
ScriptedAlchemy Sep 9, 2026
dc5faf4
chore: sync layered exposes with runtime base
ScriptedAlchemy Sep 9, 2026
960481d
chore: sync layered exposes with runtime review fixes
ScriptedAlchemy Sep 9, 2026
e30e940
fix(mf): export enhanced V1 federation options
ScriptedAlchemy Sep 8, 2026
4724c6b
Merge branch 'codex/mf-share-scope-runtime' into codex/mf-layered-con…
ScriptedAlchemy Sep 9, 2026
a00b374
Merge branch 'codex/mf-share-scope-runtime' into codex/mf-layered-con…
ScriptedAlchemy Sep 9, 2026
fca6e72
Merge branch 'codex/mf-share-scope-runtime' into codex/mf-layered-con…
ScriptedAlchemy Sep 10, 2026
1ae37ab
Merge branch 'codex/mf-share-scope-runtime' into codex/mf-layered-con…
ScriptedAlchemy Sep 10, 2026
e3dab88
Merge branch 'codex/mf-share-scope-runtime' into codex/mf-layered-con…
ScriptedAlchemy Sep 11, 2026
b55df4a
Merge branch 'stack-refresh/14911' into stack-refresh/14912
ScriptedAlchemy Sep 14, 2026
4605029
Merge branch 'stack-refresh2/14911' into stack-refresh2/14912
ScriptedAlchemy Sep 15, 2026
2e2ec31
Merge branch 'stack-refresh2/14911' into stack-refresh2/14912
ScriptedAlchemy Sep 15, 2026
12bd007
refactor(mf): carry the expose layer on ExposeOptions
ScriptedAlchemy Sep 16, 2026
5acd724
Merge branch 'stack-refresh2/14911' into stack-refresh2/14912
ScriptedAlchemy Sep 16, 2026
e4eb5ba
chore(mf): reject empty expose layer names and clean the layered fixt…
ScriptedAlchemy Sep 16, 2026
fc9224a
Merge branch 'stack-refresh2/14911' into stack-refresh2/14912
ScriptedAlchemy Sep 16, 2026
a47cc84
Merge branch 'stack-refresh2/14911' into stack-refresh2/14912
ScriptedAlchemy Sep 22, 2026
ef7c751
Merge branch 'stack-refresh2/14911' into stack-refresh2/14912
ScriptedAlchemy Sep 22, 2026
6fb8b6b
Merge ordered share scope runtime into layered container exposes
ScriptedAlchemy Sep 29, 2026
b0bf215
Merge corrected workspace lockfile into layered container exposes
ScriptedAlchemy Sep 29, 2026
3c0aed3
fix(mf): preserve unnamed consumers after base refresh
ScriptedAlchemy Sep 29, 2026
c9cb2be
fix(mf): enforce reusable expose map types and relocate Rust coverage
ScriptedAlchemy Sep 30, 2026
f65fa5e
Merge reviewed MF runtime fixes and format test dependency
ScriptedAlchemy Sep 30, 2026
046f3b2
fix(mf): preserve Rust container options source compatibility
ScriptedAlchemy Sep 30, 2026
baf20fb
Merge Rust sharing API compatibility into layered containers
ScriptedAlchemy Sep 30, 2026
1dbc84d
test(mf): retain enhanced expose serialization coverage
ScriptedAlchemy Sep 30, 2026
acf8939
Merge branch 'api-compat-runtime' into HEAD
ScriptedAlchemy Sep 30, 2026
d0d70ae
Merge branch 'api-compat-runtime' into HEAD
ScriptedAlchemy Sep 30, 2026
27c7890
Merge branch 'api-compat-runtime' into HEAD
ScriptedAlchemy Sep 30, 2026
1162106
chore: update layered exposes stack base
ScriptedAlchemy Oct 22, 2026
27998da
chore: propagate federation lockfile fix
ScriptedAlchemy Oct 22, 2026
728b7a9
chore: propagate combined preview build
ScriptedAlchemy Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/node_binding/napi-binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2302,6 +2302,7 @@ export interface RawExperiments {
export interface RawExposeOptions {
key: string
name?: string
layer?: string
import: Array<string>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl From<RawContainerPluginOptions> for ContainerPluginOptions {
pub struct RawExposeOptions {
pub key: String,
pub name: Option<String>,
pub layer: Option<String>,
pub import: Vec<String>,
}

Expand All @@ -67,6 +68,7 @@ impl From<RawExposeOptions> for (String, ExposeOptions) {
value.key,
ExposeOptions {
name: value.name,
layer: value.layer,
import: value.import,
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ impl Module for ContainerEntryModule {
Box::new(ContainerExposedDependency::new(
name.clone(),
request.clone(),
options.layer.clone(),
)) as Box<dyn Dependency>
})
.collect(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
use rspack_cacheable::{cacheable, cacheable_dyn};
use rspack_core::{
AsContextDependency, AsDependencyCodeGeneration, Dependency, DependencyCategory, DependencyId,
DependencyType, FactorizeInfo, ModuleDependency, ResourceIdentifier,
DependencyType, FactorizeInfo, ModuleDependency, ModuleLayer, ResourceIdentifier,
};

use crate::push_identifier_component;

fn exposed_resource_identifier(exposed_name: &str, request: &str, layer: Option<&str>) -> String {
let mut resource_identifier = String::from("exposed dependency ");
push_identifier_component(&mut resource_identifier, exposed_name);
push_identifier_component(&mut resource_identifier, request);
if let Some(layer) = layer {
resource_identifier.push('1');
push_identifier_component(&mut resource_identifier, layer);
} else {
resource_identifier.push('0');
}
resource_identifier
}

#[cacheable]
#[derive(Debug, Clone)]
pub struct ContainerExposedDependency {
id: DependencyId,
request: String,
pub exposed_name: String,
layer: Option<Box<ModuleLayer>>,
resource_identifier: ResourceIdentifier,
dependency_type: DependencyType,
factorize_info: FactorizeInfo,
}

impl ContainerExposedDependency {
pub fn new(exposed_name: String, request: String) -> Self {
let resource_identifier = format!("exposed dependency {exposed_name}={request}").into();
pub fn new(exposed_name: String, request: String, layer: Option<ModuleLayer>) -> Self {
Comment thread
ScriptedAlchemy marked this conversation as resolved.
Outdated
let resource_identifier =
exposed_resource_identifier(&exposed_name, &request, layer.as_deref()).into();
Self {
id: DependencyId::new(),
request,
exposed_name,
layer: layer.map(Box::new),
resource_identifier,
dependency_type: DependencyType::ContainerExposed,
factorize_info: Default::default(),
Expand All @@ -34,6 +52,7 @@ impl ContainerExposedDependency {
id: DependencyId::new(),
request,
exposed_name: String::new(),
layer: None,
resource_identifier,
dependency_type: DependencyType::ShareContainerFallback,
factorize_info: Default::default(),
Expand All @@ -55,6 +74,10 @@ impl Dependency for ContainerExposedDependency {
&self.dependency_type
}

fn get_layer(&self) -> Option<&ModuleLayer> {
self.layer.as_deref()
}

fn resource_identifier(&self) -> Option<&str> {
Some(&self.resource_identifier)
}
Expand Down Expand Up @@ -85,3 +108,15 @@ impl ModuleDependency for ContainerExposedDependency {

impl AsContextDependency for ContainerExposedDependency {}
impl AsDependencyCodeGeneration for ContainerExposedDependency {}

#[cfg(test)]
mod tests {
Comment thread
ScriptedAlchemy marked this conversation as resolved.
Outdated
use super::exposed_resource_identifier;

#[test]
fn exposed_resource_identifiers_are_collision_free() {
let first = exposed_resource_identifier("./a", "b=c|layer=foo", None);
let second = exposed_resource_identifier("./a=b", "c", Some("foo"));
assert_ne!(first, second);
}
}
5 changes: 3 additions & 2 deletions crates/rspack_plugin_mf/src/container/container_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::sync::Arc;
use rspack_core::{
ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements, CompilationParams,
CompilationRuntimeRequirementInTree, CompilerCompilation, CompilerMake, DependencyType,
EntryOptions, EntryRuntime, Filename, LibraryOptions, Plugin, RuntimeGlobals, RuntimeModule,
SourceType,
EntryOptions, EntryRuntime, Filename, LibraryOptions, ModuleLayer, Plugin, RuntimeGlobals,
RuntimeModule, SourceType,
};
use rspack_error::Result;
use rspack_hook::{plugin, plugin_hook};
Expand Down Expand Up @@ -32,6 +32,7 @@ pub struct ContainerPluginOptions {
#[derive(Debug, Clone, Serialize)]
pub struct ExposeOptions {
pub name: Option<String>,
pub layer: Option<ModuleLayer>,
Comment thread
ScriptedAlchemy marked this conversation as resolved.
Outdated
pub import: Vec<String>,
}

Expand Down
10 changes: 5 additions & 5 deletions crates/rspack_plugin_mf/src/manifest/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ pub fn empty_assets_group() -> StatsAssetsGroup {
}

pub fn normalize_assets_group(group: &mut StatsAssetsGroup) {
group.js.sync.sort();
group.js.sync.sort_unstable();
group.js.sync.dedup();
group.js.r#async.sort();
group.js.r#async.sort_unstable();
group.js.r#async.dedup();
group.css.sync.sort();
group.css.sync.sort_unstable();
group.css.sync.dedup();
group.css.r#async.sort();
group.css.r#async.sort_unstable();
group.css.r#async.dedup();
}

Expand Down Expand Up @@ -183,7 +183,7 @@ pub fn collect_usage_files_for_module(
}
}
let mut collected: Vec<String> = files.into_iter().collect();
collected.sort();
collected.sort_unstable();
collected
}

Expand Down
20 changes: 10 additions & 10 deletions crates/rspack_plugin_mf/src/manifest/data.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use serde::{Deserialize, Serialize};
use serde::Serialize;

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Clone, Default)]
pub struct StatsAssetsGroup {
#[serde(default)]
pub js: AssetsSplit,
#[serde(default)]
pub css: AssetsSplit,
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Clone, Default)]
pub struct AssetsSplit {
#[serde(default)]
pub sync: Vec<String>,
#[serde(default)]
pub r#async: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Clone, Default)]
pub struct StatsBuildInfo {
Comment thread
ScriptedAlchemy marked this conversation as resolved.
Outdated
#[serde(rename = "buildVersion")]
pub build_version: String,
Expand All @@ -28,7 +28,7 @@ pub struct StatsBuildInfo {
pub plugins: Option<Vec<String>>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Clone)]
pub struct StatsExpose {
pub path: String,
#[serde(default)]
Expand All @@ -41,7 +41,7 @@ pub struct StatsExpose {
pub assets: StatsAssetsGroup,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Clone)]
pub struct StatsShared {
pub id: String,
pub name: String,
Expand All @@ -58,7 +58,7 @@ pub struct StatsShared {
pub usedExports: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Clone)]
pub struct StatsRemote {
pub alias: String,
pub consumingFederationContainerName: String,
Expand All @@ -70,7 +70,7 @@ pub struct StatsRemote {
pub usedIn: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Clone)]
pub struct BasicStatsMetaData {
pub name: String,
pub globalName: String,
Expand All @@ -84,7 +84,7 @@ pub struct BasicStatsMetaData {
pub r#type: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Clone, Default)]
pub struct RemoteEntryMeta {
#[serde(default)]
pub name: String,
Expand All @@ -94,7 +94,7 @@ pub struct RemoteEntryMeta {
pub r#type: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Clone)]
pub struct StatsRoot {
pub id: String,
pub name: String,
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_plugin_mf/src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
let shared = shared_map
.into_values()
.map(|mut v| {
v.usedIn.sort();
v.usedIn.sort_unstable();
v.usedIn.dedup();
v
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ async fn finish_make(&self, compilation: &mut Compilation) -> Result<()> {
}
}
}
reqs.sort_by(|a, b| a[0].cmp(&b[0]).then(a[1].cmp(&b[1])));
reqs.sort_unstable_by(|a, b| a[0].cmp(&b[0]).then(a[1].cmp(&b[1])));
ordered_requests.insert(identity, reqs);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@ use rspack_hook::{plugin, plugin_hook};
use rspack_plugin_javascript::dependency::{ESMImportSpecifierDependency, ImportDependency};
use rspack_util::atom::Atom;
use rustc_hash::{FxHashMap, FxHashSet};
use serde_json::Value;

use super::{
RequestMatchKey, consume_shared_module::ConsumeSharedModule, find_exact_match,
provide_shared_module::ProvideSharedModule,
shared_used_exports_optimizer_runtime_module::SharedUsedExportsOptimizerRuntimeModule,
};
use crate::{
ShareScope, SharedIdentity, container::container_entry_module::ContainerEntryModule,
manifest::StatsRoot,
};
use crate::{ShareScope, SharedIdentity, container::container_entry_module::ContainerEntryModule};

fn shared_identity_from_output(
share_key: &str,
Expand All @@ -52,6 +50,27 @@ fn referenced_exports_for_output<'a>(
matching.next().is_none().then_some(exports)
}

fn update_shared_exports(
content: &str,
shared_referenced_exports: &FxHashMap<SharedIdentity, FxHashSet<String>>,
) -> Option<String> {
let mut root = serde_json::from_str::<Value>(content).ok()?;
for shared in root.get_mut("shared")?.as_array_mut()? {
let share_key = shared.get("name")?.as_str()?;
let Some(exports_set) = referenced_exports_for_output(shared_referenced_exports, share_key)
else {
continue;
};
let mut exports = exports_set.iter().cloned().collect::<Vec<_>>();
exports.sort_unstable();
shared.as_object_mut()?.insert(
"usedExports".to_string(),
Value::Array(exports.into_iter().map(Value::String).collect()),
);
}
serde_json::to_string_pretty(&root).ok()
}

#[derive(Debug, Clone)]
pub struct OptimizeSharedConfig {
pub request: String,
Expand Down Expand Up @@ -336,18 +355,8 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
&& let Some(file) = compilation.assets().get(file_name)
&& let Some(source) = file.get_source()
&& let SourceValue::String(content) = source.source()
&& let Ok(mut stats_root) = serde_json::from_str::<StatsRoot>(&content)
&& let Some(updated_content) = update_shared_exports(&content, &shared_referenced_exports)
{
for shared in &mut stats_root.shared {
if let Some(exports_set) =
referenced_exports_for_output(&shared_referenced_exports, &shared.name)
{
shared.usedExports = exports_set.iter().cloned().collect::<Vec<_>>();
shared.usedExports.sort();
}
}
let updated_content = serde_json::to_string_pretty(&stats_root)
.map_err(|e| rspack_error::error!("Failed to serialize stats root: {}", e))?;
compilation.update_asset(file_name, |_, info| {
Ok((RawStringSource::from(updated_content).boxed(), info))
})?;
Expand Down Expand Up @@ -532,10 +541,27 @@ mod tests {

use super::{
OptimizeSharedConfig, SharedUsedExportsOptimizerPlugin,
SharedUsedExportsOptimizerPluginOptions, referenced_exports_for_output,
SharedUsedExportsOptimizerPluginOptions, referenced_exports_for_output, update_shared_exports,
};
use crate::{ShareScope, SharedIdentity};

#[test]
fn updates_shared_exports_without_typed_deserialization() {
let identity = SharedIdentity::new(&ShareScope::Single("default".to_string()), "pkg", None);
let mut referenced_exports = FxHashMap::default();
referenced_exports.insert(
identity,
FxHashSet::from_iter(["named".to_string(), "default".to_string()]),
);
let content = r#"{"shared":[{"name":"pkg"}]}"#;

let updated = update_shared_exports(content, &referenced_exports).expect("updated");
let updated: serde_json::Value = serde_json::from_str(&updated).expect("valid json");
assert_eq!(
updated["shared"][0]["usedExports"],
serde_json::json!(["default", "named"])
);
}
#[test]
fn optimizer_keeps_same_key_and_layer_separate_by_scope() {
let plugin = SharedUsedExportsOptimizerPlugin::new(SharedUsedExportsOptimizerPluginOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl SharedUsedExportsOptimizerRuntimeModule {
.iter()
.map(|(share_key, set)| {
let mut exports: Vec<String> = set.iter().cloned().collect();
exports.sort();
exports.sort_unstable();
(share_key.clone(), exports)
})
.collect();
Expand Down
Loading
Loading