Skip to content

Commit

Permalink
review, improvements, bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Jul 19, 2023
1 parent c5dafbf commit a9167be
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 52 deletions.
42 changes: 28 additions & 14 deletions packages/next-swc/crates/napi/src/next_api/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,19 @@ use next_api::route::{Endpoint, WrittenEndpoint};
use turbo_tasks::Vc;
use turbopack_binding::turbopack::core::error::PrettyPrintError;

use super::utils::{subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc};
use super::utils::{get_issues, subscribe, NapiIssue, RootTask, TurbopackResult, VcArc};

#[napi(object)]
pub struct NapiWrittenEndpoint {
pub server_entry_path: String,
pub server_paths: Vec<String>,
pub issues: Vec<NapiIssue>,
pub diagnostics: Vec<NapiDiagnostic>,
}

impl From<&WrittenEndpoint> for NapiWrittenEndpoint {
fn from(written_endpoint: &WrittenEndpoint) -> Self {
Self {
server_entry_path: written_endpoint.server_entry_path.clone(),
server_paths: written_endpoint.server_paths.clone(),
issues: vec![],
diagnostics: vec![],
}
}
}
Expand All @@ -45,15 +41,24 @@ impl Deref for ExternalEndpoint {
#[napi]
pub async fn endpoint_write_to_disk(
#[napi(ts_arg_type = "{ __napiType: \"Endpoint\" }")] endpoint: External<ExternalEndpoint>,
) -> napi::Result<NapiWrittenEndpoint> {
) -> napi::Result<TurbopackResult<NapiWrittenEndpoint>> {
let turbo_tasks = endpoint.turbo_tasks().clone();
let endpoint = ***endpoint;
let written = turbo_tasks
.run_once(async move { endpoint.write_to_disk().strongly_consistent().await })
let (written, issues) = turbo_tasks
.run_once(async move {
let write_to_disk = endpoint.write_to_disk();
let issues = get_issues(write_to_disk).await?;
let written = write_to_disk.strongly_consistent().await?;
Ok((written, issues))
})
.await
.map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string()))?;
// TODO peek_issues and diagnostics
Ok((&*written).into())
// TODO diagnostics
Ok(TurbopackResult {
result: NapiWrittenEndpoint::from(&*written),
issues: issues.iter().map(|i| NapiIssue::from(&**i)).collect(),
diagnostics: vec![],
})
}

#[napi(ts_return_type = "{ __napiType: \"RootTask\" }")]
Expand All @@ -69,10 +74,19 @@ pub fn endpoint_changed_subscribe(
turbo_tasks,
func,
move || async move {
endpoint.changed().await?;
// TODO peek_issues and diagnostics
Ok(())
let changed = endpoint.changed();
let issues = get_issues(changed).await?;
changed.await?;
// TODO diagnostics
Ok(issues)
},
|ctx| {
let issues = ctx.value;
Ok(vec![TurbopackResult {
result: (),
issues: issues.iter().map(|i| NapiIssue::from(&**i)).collect(),
diagnostics: vec![],
}])
},
|_ctx| Ok(vec![()]),
)
}
34 changes: 18 additions & 16 deletions packages/next-swc/crates/napi/src/next_api/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use turbopack_binding::{

use super::{
endpoint::ExternalEndpoint,
utils::{serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc},
utils::{
get_issues, serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc,
},
};
use crate::register;

Expand All @@ -40,7 +42,10 @@ pub struct NapiProjectOptions {

/// A map of environment variables to use when compiling code.
pub env: Vec<NapiEnvVar>,
}

#[napi(object)]
pub struct NapiTurboEngineOptions {
/// An upper bound of memory that turbopack will attempt to stay under.
pub memory_limit: Option<f64>,
}
Expand All @@ -64,20 +69,20 @@ impl From<NapiProjectOptions> for ProjectOptions {
#[napi(ts_return_type = "{ __napiType: \"Project\" }")]
pub async fn project_new(
options: NapiProjectOptions,
turbo_engine_options: NapiTurboEngineOptions,
) -> napi::Result<External<VcArc<Vc<ProjectContainer>>>> {
register();
let turbo_tasks = TurboTasks::new(MemoryBackend::new(
options
turbo_engine_options
.memory_limit
.map(|m| m as usize)
.unwrap_or(usize::MAX),
));
let options = options.into();
let project = turbo_tasks
.run_once(async move {
let project = ProjectContainer::new(options).resolve().await?;
// get errors early
project.project().await?;
let project = ProjectContainer::new(options);
let project = project.resolve().await?;
Ok(project)
})
.await
Expand All @@ -95,19 +100,12 @@ pub async fn project_update(
>,
options: NapiProjectOptions,
) -> napi::Result<()> {
if options.memory_limit.is_some() {
return Err(napi::Error::from_reason(
"memory_limit cannot be changed after project creation".to_string(),
));
}
let turbo_tasks = project.turbo_tasks().clone();
let options = options.into();
let project = **project;
turbo_tasks
.run_once(async move {
project.update(options).await?;
// get errors early
project.project().await?;
Ok(())
})
.await
Expand Down Expand Up @@ -226,13 +224,14 @@ pub fn project_entrypoints_subscribe(
turbo_tasks.clone(),
func,
move || async move {
let entrypoints = project.project().entrypoints();
let entrypoints = project.entrypoints();
let issues = get_issues(entrypoints).await?;
let entrypoints = entrypoints.strongly_consistent().await?;
// TODO peek_issues and diagnostics
Ok(entrypoints)
Ok((entrypoints, issues))
},
move |ctx| {
let entrypoints = ctx.value;
let (entrypoints, issues) = ctx.value;
Ok(vec![NapiEntrypoints {
routes: entrypoints
.routes
Expand All @@ -246,7 +245,10 @@ pub fn project_entrypoints_subscribe(
.as_ref()
.map(|m| NapiMiddleware::from_middleware(m, &turbo_tasks))
.transpose()?,
issues: vec![],
issues: issues
.iter()
.map(|issue| NapiIssue::from(&**issue))
.collect(),
diagnostics: vec![],
}])
},
Expand Down
131 changes: 119 additions & 12 deletions packages/next-swc/crates/napi/src/next_api/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ use anyhow::{anyhow, Context, Result};
use napi::{
bindgen_prelude::{External, ToNapiValue},
threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode},
JsFunction, JsObject, NapiRaw, NapiValue, Status,
JsFunction, JsObject, JsUnknown, NapiRaw, NapiValue, Status,
};
use serde::Serialize;
use turbo_tasks::{unit, TaskId, TurboTasks};
use turbo_tasks::{unit, ReadRef, TaskId, TurboTasks, Vc};
use turbopack_binding::{
turbo::tasks_memory::MemoryBackend, turbopack::core::error::PrettyPrintError,
turbo::{tasks_fs::FileContent, tasks_memory::MemoryBackend},
turbopack::core::{
error::PrettyPrintError,
issue::{IssueContextExt, PlainIssue, PlainIssueSource, PlainSource},
source_pos::SourcePos,
},
};

/// A helper type to hold both a Vc operation and the TurboTasks root process.
Expand Down Expand Up @@ -71,8 +76,106 @@ pub fn root_task_dispose(
Ok(())
}

pub async fn get_issues<T>(source: Vc<T>) -> Result<Vec<ReadRef<PlainIssue>>> {
let issues = source
.peek_issues_with_path()
.await?
.strongly_consistent()
.await?;
issues.get_plain_issues().await
}

#[napi(object)]
pub struct NapiIssue {
pub severity: String,
pub category: String,
pub context: String,
pub title: String,
pub description: String,
pub detail: String,
pub source: Option<NapiIssueSource>,
pub documentation_link: String,
pub sub_issues: Vec<NapiIssue>,
}

impl From<&PlainIssue> for NapiIssue {
fn from(issue: &PlainIssue) -> Self {
Self {
description: issue.description.clone(),
category: issue.category.clone(),
context: issue.context.clone(),
detail: issue.detail.clone(),
documentation_link: issue.documentation_link.clone(),
severity: issue.severity.as_str().to_string(),
source: issue.source.as_deref().map(|source| source.into()),
title: issue.title.clone(),
sub_issues: issue
.sub_issues
.iter()
.map(|issue| (&**issue).into())
.collect(),
}
}
}

#[napi(object)]
pub struct NapiIssue {}
pub struct NapiIssueSource {
pub source: NapiSource,
pub start: NapiSourcePos,
pub end: NapiSourcePos,
}

impl From<&PlainIssueSource> for NapiIssueSource {
fn from(
PlainIssueSource {
asset: source,
start,
end,
}: &PlainIssueSource,
) -> Self {
Self {
source: (&**source).into(),
start: (*start).into(),
end: (*end).into(),
}
}
}

#[napi(object)]
pub struct NapiSource {
pub ident: String,
pub content: Option<String>,
}

impl From<&PlainSource> for NapiSource {
fn from(source: &PlainSource) -> Self {
Self {
ident: source.ident.to_string(),
content: match &*source.content {
FileContent::Content(content) => match content.content().to_str() {
Ok(str) => Some(str.into_owned()),
Err(_) => None,
},
FileContent::NotFound => None,
},
}
}
}

#[napi(object)]
pub struct NapiSourcePos {
pub line: u32,
pub column: u32,
}

impl From<SourcePos> for NapiSourcePos {
fn from(pos: SourcePos) -> Self {
Self {
line: pos.line as u32,
column: pos.column as u32,
}
}
}

#[napi(object)]
pub struct NapiDiagnostic {}
Expand All @@ -88,16 +191,20 @@ impl<T: ToNapiValue> ToNapiValue for TurbopackResult<T> {
env: napi::sys::napi_env,
val: Self,
) -> napi::Result<napi::sys::napi_value> {
let result = T::to_napi_value(env, val.result)?;
// let issues = ToNapiValue::to_napi_value(env, val.issues)?;
// let diagnostics = ToNapiValue::to_napi_value(env, val.diagnostics)?;

let result = JsObject::from_raw(env, result)?;

let mut obj = napi::Env::from_raw(env).create_object()?;
for key in JsObject::keys(&result)? {
obj.set_named_property(&key, result.get_named_property(&key)?)?;

let result = T::to_napi_value(env, val.result)?;
let result = JsUnknown::from_raw(env, result)?;
if matches!(result.get_type()?, napi::ValueType::Object) {
// SAFETY: We know that result is an object, so we can cast it to a JsObject
let result = unsafe { result.cast::<JsObject>() };

for key in JsObject::keys(&result)? {
let value: JsUnknown = result.get_named_property(&key)?;
obj.set_named_property(&key, value)?;
}
}

obj.set_named_property("issues", val.issues)?;
obj.set_named_property("diagnostics", val.diagnostics)?;

Expand Down
5 changes: 5 additions & 0 deletions packages/next-swc/crates/next-api/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ impl ProjectContainer {
}
.cell())
}

#[turbo_tasks::function]
pub fn entrypoints(self: Vc<Self>) -> Vc<Entrypoints> {
self.project().entrypoints()
}
}

#[turbo_tasks::value]
Expand Down
Loading

0 comments on commit a9167be

Please sign in to comment.