Skip to content

Commit

Permalink
enh: revamp ScopeHelper to BindingsHelper
Browse files Browse the repository at this point in the history
  • Loading branch information
phoenix-ru committed Oct 23, 2023
1 parent 7276158 commit aab459e
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 336 deletions.
4 changes: 2 additions & 2 deletions crates/fervid/benches/codegen_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ fn codegen_benchmark(c: &mut Criterion) {
panic!("Test component has no template block");
};

let mut scope_helper = fervid_transform::structs::ScopeHelper::default();
fervid_transform::template::transform_and_record_template(template_block, &mut scope_helper);
let mut bindings_helper = fervid_transform::structs::BindingsHelper::default();
fervid_transform::template::transform_and_record_template(template_block, &mut bindings_helper);

b.iter_batched(
|| template_block.clone(),
Expand Down
49 changes: 4 additions & 45 deletions crates/fervid_codegen/src/imports/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,67 +17,26 @@ impl CodegenContext {
self.used_imports |= vue_import;
}

pub fn get_import_str(vue_import: VueImports) -> &'static str {
match vue_import {
VueImports::CreateBlock => "_createBlock",
VueImports::CreateCommentVNode => "_createCommentVNode",
VueImports::CreateElementBlock => "_createElementBlock",
VueImports::CreateElementVNode => "_createElementVNode",
VueImports::CreateTextVNode => "_createTextVNode",
VueImports::CreateVNode => "_createVNode",
VueImports::Fragment => "_Fragment",
VueImports::KeepAlive => "_KeepAlive",
VueImports::MergeModels => "_mergeModels",
VueImports::NormalizeClass => "_normalizeClass",
VueImports::NormalizeStyle => "_normalizeStyle",
VueImports::OpenBlock => "_openBlock",
VueImports::RenderList => "_renderList",
VueImports::RenderSlot => "_renderSlot",
VueImports::ResolveComponent => "_resolveComponent",
VueImports::ResolveDirective => "_resolveDirective",
VueImports::ResolveDynamicComponent => "_resolveDynamicComponent",
VueImports::Suspense => "_Suspense",
VueImports::Teleport => "_Teleport",
VueImports::ToDisplayString => "_toDisplayString",
VueImports::Transition => "_Transition",
VueImports::TransitionGroup => "_TransitionGroup",
VueImports::UseModel => "_useModel",
VueImports::VModelCheckbox => "_vModelCheckbox",
VueImports::VModelDynamic => "_vModelDynamic",
VueImports::VModelRadio => "_vModelRadio",
VueImports::VModelSelect => "_vModelSelect",
VueImports::VModelText => "_vModelText",
VueImports::VShow => "_vShow",
VueImports::WithCtx => "_withCtx",
VueImports::WithDirectives => "_withDirectives",
VueImports::WithModifiers => "_withModifiers",
}
}

pub fn get_import_ident(vue_import: VueImports) -> JsWord {
JsWord::from(Self::get_import_str(vue_import))
}

pub fn get_and_add_import_str(&mut self, vue_import: VueImports) -> &'static str {
self.add_to_imports(vue_import);
Self::get_import_str(vue_import)
vue_import.as_str()
}

pub fn get_and_add_import_ident(&mut self, vue_import: VueImports) -> JsWord {
self.add_to_imports(vue_import);
Self::get_import_ident(vue_import)
vue_import.as_atom()
}

/// Generates all the imports used by template generation.
/// All of the imports come from 'vue'.
pub fn generate_imports(&self) -> Vec<ImportSpecifier> {
let mut result = Vec::new();
for import in self.used_imports.into_iter() {
let import_raw = Self::get_import_str(import);
let import_raw = import.as_str();

let import_local = Ident {
span: DUMMY_SP,
sym: JsWord::from(import_raw),
sym: import.as_atom(),
optional: false,
};

Expand Down
49 changes: 49 additions & 0 deletions crates/fervid_core/src/vue_imports.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use flagset::{flags, FlagSet};

use crate::FervidAtom;

flags! {
// #[derive(Clone, Copy)]
pub enum VueImports: u64 {
Expand All @@ -25,6 +27,7 @@ flags! {
ToDisplayString,
Transition,
TransitionGroup,
Unref,
UseModel,
VModelCheckbox,
VModelDynamic,
Expand All @@ -38,4 +41,50 @@ flags! {
}
}

impl VueImports {
#[inline]
pub fn as_str(self) -> &'static str {
match self {
VueImports::CreateBlock => "_createBlock",
VueImports::CreateCommentVNode => "_createCommentVNode",
VueImports::CreateElementBlock => "_createElementBlock",
VueImports::CreateElementVNode => "_createElementVNode",
VueImports::CreateTextVNode => "_createTextVNode",
VueImports::CreateVNode => "_createVNode",
VueImports::Fragment => "_Fragment",
VueImports::KeepAlive => "_KeepAlive",
VueImports::MergeModels => "_mergeModels",
VueImports::NormalizeClass => "_normalizeClass",
VueImports::NormalizeStyle => "_normalizeStyle",
VueImports::OpenBlock => "_openBlock",
VueImports::RenderList => "_renderList",
VueImports::RenderSlot => "_renderSlot",
VueImports::ResolveComponent => "_resolveComponent",
VueImports::ResolveDirective => "_resolveDirective",
VueImports::ResolveDynamicComponent => "_resolveDynamicComponent",
VueImports::Suspense => "_Suspense",
VueImports::Teleport => "_Teleport",
VueImports::ToDisplayString => "_toDisplayString",
VueImports::Transition => "_Transition",
VueImports::TransitionGroup => "_TransitionGroup",
VueImports::Unref => "_unref",
VueImports::UseModel => "_useModel",
VueImports::VModelCheckbox => "_vModelCheckbox",
VueImports::VModelDynamic => "_vModelDynamic",
VueImports::VModelRadio => "_vModelRadio",
VueImports::VModelSelect => "_vModelSelect",
VueImports::VModelText => "_vModelText",
VueImports::VShow => "_vShow",
VueImports::WithCtx => "_withCtx",
VueImports::WithDirectives => "_withDirectives",
VueImports::WithModifiers => "_withModifiers",
}
}

#[inline]
pub fn as_atom(self) -> FervidAtom {
self.as_str().into()
}
}

pub type VueImportsSet = FlagSet<VueImports>;
14 changes: 7 additions & 7 deletions crates/fervid_transform/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use fervid_core::{SfcDescriptor, SfcTemplateBlock, VueImportsSet, BindingTypes, FervidAtom, TemplateGenerationMode};
use fxhash::FxHashMap as HashMap;
use script::transform_and_record_scripts;
use structs::ScopeHelper;
use structs::BindingsHelper;
use swc_core::ecma::ast::{Module, ObjectLit, Function};
use template::transform_and_record_template;

Expand Down Expand Up @@ -41,15 +41,15 @@ pub struct TransformSfcResult {
pub fn transform_sfc(sfc_descriptor: SfcDescriptor) -> TransformSfcResult {
let mut template_block = None;

let mut scope_helper = ScopeHelper::default();
let mut bindings_helper = BindingsHelper::default();
let transform_result = transform_and_record_scripts(
sfc_descriptor.script_setup,
sfc_descriptor.script_legacy,
&mut scope_helper,
&mut bindings_helper,
);

if let Some(mut template) = sfc_descriptor.template {
transform_and_record_template(&mut template, &mut scope_helper);
transform_and_record_template(&mut template, &mut bindings_helper);
template_block = Some(template);
}

Expand All @@ -58,8 +58,8 @@ pub fn transform_sfc(sfc_descriptor: SfcDescriptor) -> TransformSfcResult {
module: transform_result.module,
setup_fn: transform_result.setup_fn,
template_block,
template_generation_mode: scope_helper.template_generation_mode,
used_idents: scope_helper.used_idents,
used_vue_imports: transform_result.added_imports,
template_generation_mode: bindings_helper.template_generation_mode,
used_idents: bindings_helper.used_bindings,
used_vue_imports: bindings_helper.vue_imports,
}
}
19 changes: 8 additions & 11 deletions crates/fervid_transform/src/script.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! Responsible for `<script>` and `<script setup>` transformations and analysis.
use fervid_core::{SfcScriptBlock, VueImportsSet, TemplateGenerationMode};
use fervid_core::{SfcScriptBlock, TemplateGenerationMode};
use swc_core::{
common::DUMMY_SP,
ecma::ast::{
Function, Module, ObjectLit, ModuleItem,
},
};

use crate::structs::{ScopeHelper, TransformScriptsResult};
use crate::structs::{BindingsHelper, TransformScriptsResult};

use self::{
options_api::{transform_and_record_script_options_api, AnalyzeOptions},
Expand All @@ -25,18 +25,18 @@ pub mod utils;
///
/// Consumes both [`SfcScriptBlock`]s to avoid cloning.
///
/// It will populate the provided [`ScopeHelper`] with the analysis information, such as:
/// It will populate the provided [`BindingsHelper`] with the analysis information, such as:
/// - Variable bindings (from `<script setup>` and from Options API);
/// - Import bindings;
/// - (TODO) Imported `.vue` component bindings;
pub fn transform_and_record_scripts(
script_setup: Option<SfcScriptBlock>,
script_legacy: Option<SfcScriptBlock>,
scope_helper: &mut ScopeHelper,
bindings_helper: &mut BindingsHelper,
) -> TransformScriptsResult {
// Set inline flag in `ScopeHelper`
// Set inline flag in `BindingsHelper`
if script_legacy.is_none() && script_setup.is_some() {
scope_helper.template_generation_mode = TemplateGenerationMode::Inline;
bindings_helper.template_generation_mode = TemplateGenerationMode::Inline;
}

//
Expand All @@ -56,7 +56,7 @@ pub fn transform_and_record_scripts(
transform_and_record_script_options_api(&mut module, AnalyzeOptions::default());

// Assign Options API bindings
scope_helper.options_api_vars = Some(script_options_transform_result.vars);
bindings_helper.options_api_bindings = Some(script_options_transform_result.vars);

//
// STEP 2: Prepare the exported object.
Expand All @@ -74,9 +74,8 @@ pub fn transform_and_record_scripts(
//

let mut setup_fn: Option<Box<Function>> = None;
let mut added_imports = VueImportsSet::default();
if let Some(script_setup) = script_setup {
let setup_transform_result = transform_and_record_script_setup(script_setup, scope_helper);
let setup_transform_result = transform_and_record_script_setup(script_setup, bindings_helper);

// TODO Push imports at module top or bottom? Or smart merge?
// TODO Merge Vue imports produced by module transformation
Expand All @@ -86,7 +85,6 @@ pub fn transform_and_record_scripts(
}

// Merge fields into an SFC exported object
added_imports = setup_transform_result.sfc_object_helper.vue_imports;
merge_sfc_helper(setup_transform_result.sfc_object_helper, &mut export_obj.props);

// TODO Adding bindings to `setup()` in Options API will get overwritten in `<script setup>`
Expand All @@ -95,7 +93,6 @@ pub fn transform_and_record_scripts(
}

TransformScriptsResult {
added_imports,
module,
export_obj,
setup_fn,
Expand Down
Loading

0 comments on commit aab459e

Please sign in to comment.