Skip to content

Commit

Permalink
feat: suppport load hook return map (#421)
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin authored Feb 4, 2024
1 parent d6a0efd commit b42b32b
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 62 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 25 additions & 24 deletions crates/rolldown/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,31 @@ workspace = true

[dependencies]

rolldown_common = { path = "../rolldown_common" }
rolldown_tracing = { path = "../rolldown_tracing" }
rolldown_utils = { path = "../rolldown_utils" }
rolldown_resolver = { path = "../rolldown_resolver" }
rolldown_error = { path = "../rolldown_error" }
rolldown_oxc = { path = "../rolldown_oxc" }
rolldown_fs = { path = "../rolldown_fs" }
derivative = { workspace = true }
sugar_path = { workspace = true }
oxc = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["rt", "macros", "sync"] }
rustc-hash = { workspace = true }
tracing = { workspace = true }
index_vec = { workspace = true }
futures = { workspace = true }
rayon = "1.6.0"
string_wizard = { workspace = true }
async-trait = { workspace = true }
smallvec = { workspace = true }
oxc_resolver = { workspace = true }
regex = { workspace = true }
once_cell = { workspace = true }
rolldown_common = { path = "../rolldown_common" }
rolldown_tracing = { path = "../rolldown_tracing" }
rolldown_utils = { path = "../rolldown_utils" }
rolldown_resolver = { path = "../rolldown_resolver" }
rolldown_error = { path = "../rolldown_error" }
rolldown_oxc = { path = "../rolldown_oxc" }
rolldown_fs = { path = "../rolldown_fs" }
rolldown_sourcemap = { path = "../rolldown_sourcemap" }
derivative = { workspace = true }
sugar_path = { workspace = true }
oxc = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["rt", "macros", "sync"] }
rustc-hash = { workspace = true }
tracing = { workspace = true }
index_vec = { workspace = true }
futures = { workspace = true }
rayon = "1.6.0"
string_wizard = { workspace = true }
async-trait = { workspace = true }
smallvec = { workspace = true }
oxc_resolver = { workspace = true }
regex = { workspace = true }
once_cell = { workspace = true }

[dev_dependencies]
insta = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions crates/rolldown/src/bundler/module/normal_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub struct NormalModule {
pub exports_kind: ExportsKind,
pub scope: AstScope,
pub default_export_ref: SymbolRef,
pub sourcemap_chain: Vec<rolldown_sourcemap::SourceMap>,
}

impl NormalModule {
Expand Down
2 changes: 2 additions & 0 deletions crates/rolldown/src/bundler/module/normal_module_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct NormalModuleBuilder {
pub module_type: ModuleType,
pub is_user_defined_entry: Option<bool>,
pub pretty_path: Option<String>,
pub sourcemap_chain: Vec<rolldown_sourcemap::SourceMap>,
}

impl NormalModuleBuilder {
Expand All @@ -57,6 +58,7 @@ impl NormalModuleBuilder {
module_type: self.module_type,
is_user_defined_entry: self.is_user_defined_entry.unwrap(),
pretty_path: self.pretty_path.unwrap(),
sourcemap_chain: self.sourcemap_chain,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ impl<'task, T: FileSystem + Default + 'static> NormalModuleTask<'task, T> {
async fn run_inner(&mut self) -> BatchedResult<()> {
tracing::trace!("process {:?}", self.resolved_path);

let mut sourcemap_chain = vec![];
let mut warnings = vec![];

// Run plugin load to get content first, if it is None using read fs as fallback.
let source = load_source(&self.ctx.plugin_driver, &self.resolved_path, &self.ctx.fs).await?;
let source =
load_source(&self.ctx.plugin_driver, &self.resolved_path, &self.ctx.fs, &mut sourcemap_chain)
.await?;

// Run plugin transform.
let source: Arc<str> = transform_source(&self.ctx.plugin_driver, source).await?.into();
Expand Down Expand Up @@ -99,6 +102,7 @@ impl<'task, T: FileSystem + Default + 'static> NormalModuleTask<'task, T> {
namespace_symbol: Some(namespace_symbol),
module_type: self.module_type,
pretty_path: Some(self.resolved_path.prettify(&self.ctx.input_options.cwd)),
sourcemap_chain,
..Default::default()
};

Expand Down
5 changes: 5 additions & 0 deletions crates/rolldown/src/bundler/utils/load_source.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rolldown_common::ResolvedPath;
use rolldown_sourcemap::SourceMap;
use sugar_path::AsPath;

use crate::{bundler::plugin_driver::PluginDriver, error::BatchedErrors, HookLoadArgs};
Expand All @@ -7,9 +8,13 @@ pub async fn load_source(
plugin_driver: &PluginDriver,
resolved_path: &ResolvedPath,
fs: &dyn rolldown_fs::FileSystem,
sourcemap_chain: &mut Vec<SourceMap>,
) -> Result<String, BatchedErrors> {
let source =
if let Some(r) = plugin_driver.load(&HookLoadArgs { id: &resolved_path.path }).await? {
if let Some(map) = r.map {
sourcemap_chain.push(map);
}
r.code
} else if resolved_path.ignored {
String::new()
Expand Down
2 changes: 2 additions & 0 deletions crates/rolldown/src/plugin/output.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rolldown_sourcemap::SourceMap;
#[derive(Debug)]
pub struct HookResolveIdOutput {
pub id: String,
Expand All @@ -7,6 +8,7 @@ pub struct HookResolveIdOutput {
#[derive(Debug)]
pub struct HookLoadOutput {
pub code: String,
pub map: Option<SourceMap>,
}

#[derive(Debug)]
Expand Down
72 changes: 40 additions & 32 deletions crates/rolldown_binding/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,39 @@

/* auto-generated by NAPI-RS */

export interface InputItem {
name?: string
import: string
}
export interface ResolveOptions {
alias?: Record<string, Array<string>>
aliasFields?: Array<Array<string>>
conditionNames?: Array<string>
exportsFields?: Array<Array<string>>
extensions?: Array<string>
mainFields?: Array<string>
mainFiles?: Array<string>
modules?: Array<string>
symlinks?: boolean
}
export interface InputOptions {
external?: (
source: string,
importer?: string,
isResolved?: boolean,
) => boolean
input: Array<InputItem>
plugins: Array<PluginOptions>
resolve?: ResolveOptions
cwd: string
}
export interface OutputOptions {
entryFileNames?: string
chunkFileNames?: string
dir?: string
exports?: 'default' | 'named' | 'none' | 'auto'
format?: 'esm' | 'cjs'
}
export interface PluginOptions {
name: string
buildStart?: () => Promise<void>
Expand Down Expand Up @@ -31,6 +64,7 @@ export interface ResolveIdResult {
}
export interface SourceResult {
code: string
map?: SourceMap
}
export interface HookRenderChunkOutput {
code: string
Expand All @@ -51,38 +85,12 @@ export interface RenderedChunk {
fileName: string
modules: Record<string, RenderedModule>
}
export interface InputItem {
name?: string
import: string
}
export interface ResolveOptions {
alias?: Record<string, Array<string>>
aliasFields?: Array<Array<string>>
conditionNames?: Array<string>
exportsFields?: Array<Array<string>>
extensions?: Array<string>
mainFields?: Array<string>
mainFiles?: Array<string>
modules?: Array<string>
symlinks?: boolean
}
export interface InputOptions {
external?: (
source: string,
importer?: string,
isResolved?: boolean,
) => boolean
input: Array<InputItem>
plugins: Array<PluginOptions>
resolve?: ResolveOptions
cwd: string
}
export interface OutputOptions {
entryFileNames?: string
chunkFileNames?: string
dir?: string
exports?: 'default' | 'named' | 'none' | 'auto'
format?: 'esm' | 'cjs'
export interface SourceMap {
mappings: string
names: Array<string>
sourceRoot?: string
sources: Array<string>
sourcesContent: Array<string>
}
export interface RenderedModule {
code?: string
Expand Down
5 changes: 4 additions & 1 deletion crates/rolldown_binding/src/options/plugin/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use derivative::Derivative;
use napi::JsFunction;
use serde::Deserialize;

use crate::options::sourcemap::SourceMap;

#[napi_derive::napi(object)]
#[derive(Deserialize, Default, Derivative)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -92,11 +94,12 @@ impl From<ResolveIdResult> for rolldown::HookResolveIdOutput {
#[derivative(Debug)]
pub struct SourceResult {
pub code: String,
pub map: Option<SourceMap>,
}

impl From<SourceResult> for rolldown::HookLoadOutput {
fn from(value: SourceResult) -> Self {
Self { code: value.code }
Self { code: value.code, map: value.map.map(Into::into) }
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/rolldown_plugin_vite_scanner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ impl<T: FileSystem + 'static + Default> Plugin for ViteScannerPlugin<T> {
scripts.into_iter().for_each(|(key, value)| {
self.scripts.insert(key, value);
});
return Ok(Some(HookLoadOutput { code: content }));
return Ok(Some(HookLoadOutput { code: content, map: None }));
}

// load local scripts (`<script>` in Svelte and `<script setup>` in Vue)
if VIRTUAL_MODULE_REGEX.is_match(id) {
let key = id.replace(VIRTUAL_MODULE_PREFIX, "");
if let Some(content) = self.scripts.get(&key) {
return Ok(Some(HookLoadOutput { code: content.to_string() }));
return Ok(Some(HookLoadOutput { code: content.to_string(), map: None }));
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/node/src/options/create-build-plugin-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
HookRenderChunkOutput,
Outputs,
} from '@rolldown/node-binding'
import { transformToOutputBundle, unimplemented } from '../utils'
import { transformToOutputBundle, unimplemented, transformSourcemap } from '../utils'

// Note: because napi not catch error, so we need to catch error and print error to debugger in adapter.
export function createBuildPluginAdapter(
Expand Down Expand Up @@ -275,7 +275,7 @@ function load(hook: Plugin['load']) {
return
}
// TODO other filed
return { code: value.code }
return { code: value.code, map: transformSourcemap(value.map) }
} catch (error) {
console.error(error)
throw error
Expand Down
1 change: 1 addition & 0 deletions packages/node/src/rollup-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export type {
NormalizedInputOptions,
OutputAsset,
OutputBundle,
SourceMapInput
} from 'rollup'
1 change: 1 addition & 0 deletions packages/node/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './transform-to-rollup-output'
export * from './normalize-plugin-option'
export * from './ensure-array'
export * from './create-bundler'
export * from './transform-sourcemap'

export function arraify<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value]
Expand Down
27 changes: 27 additions & 0 deletions packages/node/src/utils/transform-sourcemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type {
SourceMap
} from '@rolldown/node-binding'

import type {
SourceMapInput
} from '../rollup-types'


export function transformSourcemap(value?: SourceMapInput): SourceMap | undefined {
if (value === undefined || value === null) {
return
}
if (typeof value === 'string') {
return JSON.parse(value) as SourceMap
}
if (typeof value === 'object') {
return {
// TODO file, version, x_google_ignoreList
mappings: value.mappings,
names: 'names' in value ? value.names : [],
sourceRoot: 'sourceRoot' in value ? value.sourceRoot : "",
sources: 'sources' in value ? value.sources : [],
sourcesContent: 'sourcesContent' in value ? value.sourcesContent ? value.sourcesContent.filter((v) => typeof v === 'string') as string [] : [] : [],
}
}
}
1 change: 1 addition & 0 deletions packages/node/test/cases/plugin/load/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const config: RollupOptions = {
if (id === 'foo') {
return {
code: `console.log('foo')`,
map: { mappings: "" }
}
}
},
Expand Down

0 comments on commit b42b32b

Please sign in to comment.