Skip to content

Commit

Permalink
feat: ContextModuleFactoryBeforeResolveData
Browse files Browse the repository at this point in the history
  • Loading branch information
SyMind committed Sep 23, 2024
1 parent 6e87fee commit 9cc09f4
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 17 deletions.
6 changes: 3 additions & 3 deletions crates/rspack_binding_values/src/context_module_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ impl JsContextModuleFactoryAfterResolveData {
}

#[napi(getter)]
pub fn dependencies(&self) -> Vec<JsDependency> {
pub fn dependencies(&mut self) -> Vec<JsDependency> {
self
.0
.dependencies
.iter()
.map(|dep| JsDependency::new(dep.clone()))
.iter_mut()
.map(|dep| JsDependency::new(dep))
.collect::<Vec<_>>()
}
}
Expand Down
14 changes: 12 additions & 2 deletions crates/rspack_binding_values/src/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use rspack_core::{
ModuleGraph,
};

// JsCompiledDependency allows JS-side access to a Dependency instance that has already
// been processed and stored in the Compilation.
#[napi]
pub struct JsCompiledDependency {
pub(crate) dependency_id: DependencyId,
Expand Down Expand Up @@ -65,11 +67,19 @@ impl JsCompiledDependency {
}
}

// JsDependency represents a Dependency instance that is currently being processed.
// It is in the make stage and has not yet been added to the Compilation.
#[napi]
pub struct JsDependency(BoxDependency);
pub struct JsDependency(&'static mut BoxDependency);

impl JsDependency {
pub(crate) fn new(dependency: BoxDependency) -> Self {
pub(crate) fn new(dependency: &mut BoxDependency) -> Self {
// SAFETY:
// The lifetime of the &mut BoxDependency reference is extended to 'static.
// This is safe because the JS side will guarantee that the JsDependency instance's
// lifetime is properly managed and restricted.
let dependency =
unsafe { std::mem::transmute::<&mut BoxDependency, &'static mut BoxDependency>(dependency) };
Self(dependency)
}
}
Expand Down
24 changes: 19 additions & 5 deletions packages/rspack/src/Compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { ThreadsafeWritableNodeFS } from "./FileSystem";
import {
CodeGenerationResult,
ContextModuleFactoryAfterResolveData,
ContextModuleFactoryBeforeResolveData,
Module
} from "./Module";
import { NormalModuleFactory } from "./NormalModuleFactory";
Expand Down Expand Up @@ -1159,7 +1160,18 @@ class Compiler {
| false
| binding.JsContextModuleFactoryBeforeResolveData
) => {
return queried.promise(bindingData);
const data = bindingData
? ContextModuleFactoryBeforeResolveData.__from_binding(
bindingData
)
: false;
const result = await queried.promise(data);
if (data) {
ContextModuleFactoryBeforeResolveData.__drop(data);
}
return result
? ContextModuleFactoryBeforeResolveData.__to_binding(result)
: false;
}
),
registerContextModuleFactoryAfterResolveTaps:
Expand All @@ -1178,11 +1190,13 @@ class Compiler {
bindingData
)
: false;
const ret = await queried.promise(data);
const result = ret
? ContextModuleFactoryAfterResolveData.__to_binding(ret)
const result = await queried.promise(data);
if (data) {
ContextModuleFactoryAfterResolveData.__drop(data);
}
return result
? ContextModuleFactoryAfterResolveData.__to_binding(result)
: false;
return result;
}
),
registerJavascriptModulesChunkHashTaps: this.#createHookRegisterTaps(
Expand Down
18 changes: 18 additions & 0 deletions packages/rspack/src/Dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,52 @@ import { JsDependency, JsCompiledDependency } from "@rspack/binding";

export class Dependency {
#binding: JsDependency | JsCompiledDependency;
#dropped = false;

static __from_binding(
binding: JsDependency | JsCompiledDependency
): Dependency {
return new Dependency(binding);
}

static __drop(dependency: Dependency) {
dependency.#dropped = true;
}

private ensureValidLifecycle() {
if (this.#dropped) {
throw new Error(
"The Dependency has exceeded its lifecycle and has been dropped by Rust."
);
}
}

private constructor(binding: JsDependency | JsCompiledDependency) {
this.#binding = binding;
}

get type(): string {
this.ensureValidLifecycle();
return this.#binding.type;
}

get category(): string {
this.ensureValidLifecycle();
return this.#binding.category;
}

get request(): string | undefined {
this.ensureValidLifecycle();
return this.#binding.request;
}

get critital(): boolean | undefined {
this.ensureValidLifecycle();
return this.#binding.critical;
}

set critital(critital: boolean | undefined) {
this.ensureValidLifecycle();
if (
typeof critital === "boolean" &&
this.#binding instanceof JsDependency
Expand Down
131 changes: 124 additions & 7 deletions packages/rspack/src/Module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
JsCodegenerationResult,
JsContextModuleFactoryAfterResolveData,
JsContextModuleFactoryBeforeResolveData,
JsCreateData,
JsFactoryMeta,
JsModule,
Expand Down Expand Up @@ -36,45 +37,151 @@ export type ResolveData = {
createData?: CreateData;
};

export class ContextModuleFactoryBeforeResolveData {
#inner: JsContextModuleFactoryBeforeResolveData;
#dropped = false;

static __from_binding(binding: JsContextModuleFactoryBeforeResolveData) {
return new ContextModuleFactoryBeforeResolveData(binding);
}

static __to_binding(
data: ContextModuleFactoryBeforeResolveData
): JsContextModuleFactoryBeforeResolveData {
return data.#inner;
}

static __drop(data: ContextModuleFactoryBeforeResolveData) {
data.#dropped = true;
}

private constructor(binding: JsContextModuleFactoryBeforeResolveData) {
this.#inner = binding;
}

private ensureValidLifecycle() {
if (this.#dropped) {
throw new Error(
"The ContextModuleFactoryBeforeResolveData has exceeded its lifecycle and has been dropped by Rust."
);
}
}

get context(): string {
this.ensureValidLifecycle();
return this.#inner.context;
}

set context(val: string) {
this.ensureValidLifecycle();
this.#inner.context = val;
}

get request(): string {
this.ensureValidLifecycle();
return this.#inner.request;
}

set request(val: string) {
this.#inner.request = val;
}

get regExp(): RegExp | undefined {
this.ensureValidLifecycle();
if (!this.#inner.regExp) {
return undefined;
}
const { source, flags } = this.#inner.regExp;
return new RegExp(source, flags);
}

set regExp(val: RegExp | undefined) {
this.ensureValidLifecycle();
if (!val) {
this.#inner.regExp = undefined;
return;
}
this.#inner.regExp = {
source: val.source,
flags: val.flags
};
}

get recursive(): boolean {
this.ensureValidLifecycle();
return this.#inner.recursive;
}

set recursive(val: boolean) {
this.ensureValidLifecycle();
this.#inner.recursive = val;
}
}

export type ContextModuleFactoryBeforeResolveResult =
| false
| {
context: string;
request?: string;
};
| ContextModuleFactoryBeforeResolveData;

export class ContextModuleFactoryAfterResolveData {
#inner: JsContextModuleFactoryAfterResolveData;
#resolvedDependencies?: Dependency[];
#dropped = false;
#dropWarningMessage?: string;

static __from_binding(binding: JsContextModuleFactoryAfterResolveData) {
return new ContextModuleFactoryAfterResolveData(binding);
}

static __to_binding(data: ContextModuleFactoryAfterResolveData) {
static __to_binding(
data: ContextModuleFactoryAfterResolveData
): JsContextModuleFactoryAfterResolveData {
return data.#inner;
}

constructor(data: JsContextModuleFactoryAfterResolveData) {
static __drop(data: ContextModuleFactoryAfterResolveData) {
data.#dropped = true;
if (data.#resolvedDependencies) {
data.#resolvedDependencies.forEach(dependency =>
Dependency.__drop(dependency)
);
}
}

private ensureValidLifecycle() {
if (this.#dropped) {
throw new Error(
this.#dropWarningMessage ??
"The ContextModuleFactoryAfterResolveData has exceeded its lifecycle and has been dropped by Rust."
);
}
}

private constructor(data: JsContextModuleFactoryAfterResolveData) {
this.#inner = data;
}

get resource(): string {
this.ensureValidLifecycle();
return this.#inner.resource;
}

set resource(val: string) {
this.ensureValidLifecycle();
this.#inner.resource = val;
}

get context(): string {
this.ensureValidLifecycle();
return this.#inner.context;
}

set context(val: string) {
this.ensureValidLifecycle();
this.#inner.context = val;
}

get request(): string {
this.ensureValidLifecycle();
return this.#inner.request;
}

Expand All @@ -83,6 +190,7 @@ export class ContextModuleFactoryAfterResolveData {
}

get regExp(): RegExp | undefined {
this.ensureValidLifecycle();
if (!this.#inner.regExp) {
return undefined;
}
Expand All @@ -91,6 +199,7 @@ export class ContextModuleFactoryAfterResolveData {
}

set regExp(val: RegExp | undefined) {
this.ensureValidLifecycle();
if (!val) {
this.#inner.regExp = undefined;
return;
Expand All @@ -102,15 +211,23 @@ export class ContextModuleFactoryAfterResolveData {
}

get recursive(): boolean {
this.ensureValidLifecycle();
return this.#inner.recursive;
}

set recursive(val: boolean) {
this.ensureValidLifecycle();
this.#inner.recursive = val;
}

get dependencies(): Dependency[] {
return this.#inner.dependencies.map(dep => Dependency.__from_binding(dep));
this.ensureValidLifecycle();
if (!this.#resolvedDependencies) {
this.#resolvedDependencies = this.#inner.dependencies.map(dep =>
Dependency.__from_binding(dep)
);
}
return this.#resolvedDependencies;
}
}

Expand Down

0 comments on commit 9cc09f4

Please sign in to comment.