Skip to content

Commit

Permalink
Add support for FreeVarReference::Error (vercel/turborepo#6177)
Browse files Browse the repository at this point in the history
### Description

Next.js needs a way to error when certain globals are used in the edge
runtime. For example `setImmediate`, to cause an error at compile time.
This implements support for `FreeVarReference::Error` which can be used
to provide an error message.
Since the internals already track the span the message is applied with
the right code location automatically.

<!--
  ✍️ Write a short summary of your work.
  If necessary, include relevant screenshots.
-->

### Testing Instructions

<!--
  Give a quick description of steps to test your changes.
-->
  • Loading branch information
timneutkens committed Oct 15, 2023
1 parent 9cb212c commit 750f81e
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 6 deletions.
1 change: 1 addition & 0 deletions crates/turbopack-core/src/compile_time_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ pub enum FreeVarReference {
export: Option<String>,
},
Value(CompileTimeDefineValue),
Error(String),
}

impl From<bool> for FreeVarReference {
Expand Down
1 change: 1 addition & 0 deletions crates/turbopack-ecmascript/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ pub mod failed_to_analyse {
pub const NODE_PROTOBUF_LOADER: &str = "TP1105";
pub const AMD_DEFINE: &str = "TP1200";
pub const NEW_URL_IMPORT_META: &str = "TP1201";
pub const FREE_VAR_REFERENCE: &str = "TP1202";
}
}
25 changes: 19 additions & 6 deletions crates/turbopack-ecmascript/src/references/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,22 +896,22 @@ pub(crate) async fn analyze_ecmascript_module(
Effect::FreeVar {
var,
ast_path,
span: _,
span,
in_try: _,
} => {
handle_free_var(&ast_path, var, &analysis_state, &mut analysis).await?;
handle_free_var(&ast_path, var, span, &analysis_state, &mut analysis).await?;
}
Effect::Member {
obj,
prop,
ast_path,
span: _,
span,
in_try,
} => {
let obj = analysis_state.link_value(obj, in_try).await?;
let prop = analysis_state.link_value(prop, in_try).await?;

handle_member(&ast_path, obj, prop, &analysis_state, &mut analysis).await?;
handle_member(&ast_path, obj, prop, span, &analysis_state, &mut analysis).await?;
}
Effect::ImportedBinding {
esm_reference_index,
Expand Down Expand Up @@ -1637,6 +1637,7 @@ async fn handle_member(
ast_path: &[AstParentKind],
obj: JsValue,
prop: JsValue,
span: Span,
state: &AnalysisState<'_>,
analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
) -> Result<()> {
Expand All @@ -1653,7 +1654,7 @@ async fn handle_member(
continue;
}
if obj.iter_defineable_name_rev().eq(it)
&& handle_free_var_reference(ast_path, value, state, analysis).await?
&& handle_free_var_reference(ast_path, value, span, state, analysis).await?
{
return Ok(());
}
Expand All @@ -1680,6 +1681,7 @@ async fn handle_member(
async fn handle_free_var(
ast_path: &[AstParentKind],
var: JsValue,
span: Span,
state: &AnalysisState<'_>,
analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
) -> Result<()> {
Expand All @@ -1690,10 +1692,11 @@ async fn handle_free_var(
if name.len() != def_name_len {
continue;
}

if var
.iter_defineable_name_rev()
.eq(name.iter().map(Cow::Borrowed).rev())
&& handle_free_var_reference(ast_path, value, state, analysis).await?
&& handle_free_var_reference(ast_path, value, span, state, analysis).await?
{
return Ok(());
}
Expand All @@ -1706,6 +1709,7 @@ async fn handle_free_var(
async fn handle_free_var_reference(
ast_path: &[AstParentKind],
value: &FreeVarReference,
span: Span,
state: &AnalysisState<'_>,
analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
) -> Result<bool> {
Expand All @@ -1722,7 +1726,16 @@ async fn handle_free_var_reference(
) {
return Ok(false);
}

match value {
FreeVarReference::Error(error_message) => state.handler.span_err_with_code(
span,
error_message,
DiagnosticId::Error(
errors::failed_to_analyse::ecmascript::FREE_VAR_REFERENCE.to_string(),
),
),

FreeVarReference::Value(value) => {
analysis.add_code_gen(ConstantValue::new(
Value::new(value.clone()),
Expand Down

0 comments on commit 750f81e

Please sign in to comment.