mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 17:54:15 +03:00
fix(webpack/ast): Handle typescript (#3045)
swc_webpack_ast: - Add `proces_file`. - Add support for typescript.
This commit is contained in:
parent
9b36abbe75
commit
24179bd9be
@ -9,6 +9,7 @@ export RUST_BACKTRACE=1
|
|||||||
cargo test --no-run
|
cargo test --no-run
|
||||||
UPDATE=1 cargo test -q
|
UPDATE=1 cargo test -q
|
||||||
|
|
||||||
(cd next.js/packages/next-swc && yarn build-native)
|
(cd next.js/packages/next-swc && yarn build-native --release)
|
||||||
|
|
||||||
(cd next.js && NEXT_PRIVATE_LOCAL_WEBPACK5=1 yarn next dev test/integration/production)
|
(cd next.js && NEXT_PRIVATE_LOCAL_WEBPACK5=1 yarn testheadless $@ || true)
|
||||||
|
(cd next.js && NEXT_PRIVATE_LOCAL_WEBPACK5=1 yarn next dev $@)
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
use crate::reducer::ast_reducer;
|
use crate::reducer::ast_reducer;
|
||||||
use anyhow::{Context, Error};
|
use anyhow::{anyhow, Context, Error};
|
||||||
use swc_common::{sync::Lrc, Mark, SourceFile, SourceMap};
|
use serde::Serialize;
|
||||||
|
use swc_common::{
|
||||||
|
errors::HANDLER, sync::Lrc, FileName, FilePathMapping, Globals, Mark, SourceFile, SourceMap,
|
||||||
|
GLOBALS,
|
||||||
|
};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
|
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax, TsConfig};
|
||||||
use swc_ecma_transforms_base::resolver::resolver_with_mark;
|
use swc_ecma_transforms_base::resolver::resolver_with_mark;
|
||||||
use swc_ecma_visit::VisitMutWith;
|
use swc_ecma_visit::VisitMutWith;
|
||||||
use swc_estree_ast::flavor::Flavor;
|
use swc_estree_ast::flavor::Flavor;
|
||||||
@ -10,6 +15,73 @@ use swc_timer::timer;
|
|||||||
|
|
||||||
pub mod reducer;
|
pub mod reducer;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct AstOutput {
|
||||||
|
ast: String,
|
||||||
|
src: Option<Lrc<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_file<F>(load_file: F, include_src: bool) -> Result<AstOutput, Error>
|
||||||
|
where
|
||||||
|
F: FnOnce(&Lrc<SourceMap>) -> Result<Lrc<SourceFile>, Error>,
|
||||||
|
{
|
||||||
|
let globals = Globals::new();
|
||||||
|
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
|
|
||||||
|
let fm = load_file(&cm).context("failed to load file")?;
|
||||||
|
|
||||||
|
// Default
|
||||||
|
let syntax = Syntax::Es(EsConfig {
|
||||||
|
jsx: true,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
let syntax = match &fm.name {
|
||||||
|
FileName::Real(path) => match path.extension() {
|
||||||
|
Some(ext) => {
|
||||||
|
if ext == "tsx" {
|
||||||
|
Syntax::Typescript(TsConfig {
|
||||||
|
tsx: true,
|
||||||
|
no_early_errors: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
} else if ext == "ts" {
|
||||||
|
Syntax::Typescript(TsConfig {
|
||||||
|
no_early_errors: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
syntax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => syntax,
|
||||||
|
},
|
||||||
|
_ => syntax,
|
||||||
|
};
|
||||||
|
|
||||||
|
let module = {
|
||||||
|
let lexer = Lexer::new(syntax, EsVersion::latest(), StringInput::from(&*fm), None);
|
||||||
|
let mut parser = Parser::new_from(lexer);
|
||||||
|
|
||||||
|
parser.parse_module().map_err(|err| {
|
||||||
|
HANDLER.with(|h| {
|
||||||
|
err.into_diagnostic(h).emit();
|
||||||
|
anyhow!("failed to parse module")
|
||||||
|
})
|
||||||
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
|
let ast = GLOBALS.set(&globals, || webpack_ast(cm.clone(), fm.clone(), module))?;
|
||||||
|
|
||||||
|
Ok(AstOutput {
|
||||||
|
ast,
|
||||||
|
src: if include_src {
|
||||||
|
Some(fm.src.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// `n` is expected to be pure (`resolver` is not applied)
|
/// `n` is expected to be pure (`resolver` is not applied)
|
||||||
pub fn webpack_ast(
|
pub fn webpack_ast(
|
||||||
cm: Lrc<SourceMap>,
|
cm: Lrc<SourceMap>,
|
||||||
@ -27,6 +99,7 @@ pub fn webpack_ast(
|
|||||||
let _timer = timer!("resolver");
|
let _timer = timer!("resolver");
|
||||||
n.visit_mut_with(&mut resolver_with_mark(top_level_mark));
|
n.visit_mut_with(&mut resolver_with_mark(top_level_mark));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
n.visit_mut_with(&mut ast_reducer(top_level_mark));
|
n.visit_mut_with(&mut ast_reducer(top_level_mark));
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use self::flatten::contains_import;
|
use self::{flatten::contains_import, typescript::ts_remover};
|
||||||
use std::{iter::once, sync::Arc};
|
use std::{iter::once, sync::Arc};
|
||||||
use swc_atoms::js_word;
|
use swc_atoms::js_word;
|
||||||
use swc_common::{
|
use swc_common::{
|
||||||
collections::AHashSet,
|
collections::{AHashMap, AHashSet},
|
||||||
pass::{Repeat, Repeated},
|
pass::{Repeat, Repeated},
|
||||||
util::take::Take,
|
util::take::Take,
|
||||||
Mark, Span, Spanned, SyntaxContext,
|
Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_utils::{ident::IdentLike, Id, IsEmpty, StmtLike, StmtOrModuleItem};
|
use swc_ecma_utils::{ident::IdentLike, Id, IsEmpty, StmtLike, StmtOrModuleItem};
|
||||||
@ -13,6 +13,7 @@ use swc_ecma_visit::{Visit, VisitMut, VisitMutWith, VisitWith};
|
|||||||
use swc_timer::timer;
|
use swc_timer::timer;
|
||||||
|
|
||||||
mod flatten;
|
mod flatten;
|
||||||
|
mod typescript;
|
||||||
|
|
||||||
/// # Usage
|
/// # Usage
|
||||||
///
|
///
|
||||||
@ -68,11 +69,24 @@ pub fn ast_reducer(top_level_mark: Mark) -> impl VisitMut {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
struct BindingInfo {
|
||||||
|
used_as_type: bool,
|
||||||
|
used_as_var: bool,
|
||||||
|
}
|
||||||
|
|
||||||
struct Analyzer {
|
struct Analyzer {
|
||||||
amd_requires: AHashSet<Id>,
|
amd_requires: AHashSet<Id>,
|
||||||
|
used_refs: AHashMap<Id, BindingInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visit for Analyzer {
|
impl Visit for Analyzer {
|
||||||
|
fn visit_assign_pat_prop(&mut self, p: &AssignPatProp) {
|
||||||
|
p.visit_children_with(self);
|
||||||
|
|
||||||
|
self.used_refs.entry(p.key.to_id()).or_default().used_as_var = true;
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_call_expr(&mut self, e: &CallExpr) {
|
fn visit_call_expr(&mut self, e: &CallExpr) {
|
||||||
e.visit_children_with(self);
|
e.visit_children_with(self);
|
||||||
|
|
||||||
@ -124,6 +138,64 @@ impl Visit for Analyzer {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, e: &Expr) {
|
||||||
|
e.visit_children_with(self);
|
||||||
|
|
||||||
|
match e {
|
||||||
|
Expr::Ident(i) => {
|
||||||
|
self.used_refs.entry(i.to_id()).or_default().used_as_var = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_member_expr(&mut self, e: &MemberExpr) {
|
||||||
|
e.obj.visit_with(self);
|
||||||
|
|
||||||
|
if e.computed {
|
||||||
|
e.prop.visit_with(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_pat(&mut self, p: &Pat) {
|
||||||
|
p.visit_children_with(self);
|
||||||
|
|
||||||
|
match p {
|
||||||
|
Pat::Ident(s) => {
|
||||||
|
self.used_refs.entry(s.to_id()).or_default().used_as_var = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_prop(&mut self, p: &Prop) {
|
||||||
|
p.visit_children_with(self);
|
||||||
|
|
||||||
|
match p {
|
||||||
|
Prop::Shorthand(s) => {
|
||||||
|
self.used_refs.entry(s.to_id()).or_default().used_as_var = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_ts_type_ref(&mut self, ty: &TsTypeRef) {
|
||||||
|
fn left_most(n: &TsEntityName) -> &Ident {
|
||||||
|
match n {
|
||||||
|
TsEntityName::Ident(i) => i,
|
||||||
|
TsEntityName::TsQualifiedName(q) => left_most(&q.left),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ty.visit_children_with(self);
|
||||||
|
|
||||||
|
let left = left_most(&ty.type_name);
|
||||||
|
self.used_refs.entry(left.to_id()).or_default().used_as_type = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -131,6 +203,9 @@ struct ScopeData {
|
|||||||
imported_ids: AHashSet<Id>,
|
imported_ids: AHashSet<Id>,
|
||||||
/// amd `require` modules.
|
/// amd `require` modules.
|
||||||
amd_requires: AHashSet<Id>,
|
amd_requires: AHashSet<Id>,
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
used_refs: AHashMap<Id, BindingInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScopeData {
|
impl ScopeData {
|
||||||
@ -160,7 +235,8 @@ impl ScopeData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut analyzer = Analyzer {
|
let mut analyzer = Analyzer {
|
||||||
amd_requires: AHashSet::default(),
|
amd_requires: Default::default(),
|
||||||
|
used_refs: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
items.visit_with(&mut analyzer);
|
items.visit_with(&mut analyzer);
|
||||||
@ -168,6 +244,7 @@ impl ScopeData {
|
|||||||
ScopeData {
|
ScopeData {
|
||||||
imported_ids,
|
imported_ids,
|
||||||
amd_requires: analyzer.amd_requires,
|
amd_requires: analyzer.amd_requires,
|
||||||
|
used_refs: analyzer.used_refs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,22 +868,6 @@ impl VisitMut for ReduceAst {
|
|||||||
*e = *expr.arg.take();
|
*e = *expr.arg.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::TsAs(expr) => {
|
|
||||||
*e = *expr.expr.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::TsConstAssertion(expr) => {
|
|
||||||
*e = *expr.expr.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::TsTypeAssertion(expr) => {
|
|
||||||
*e = *expr.expr.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::TsNonNull(expr) => {
|
|
||||||
*e = *expr.expr.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::TaggedTpl(expr) => {
|
Expr::TaggedTpl(expr) => {
|
||||||
let mut exprs = Vec::with_capacity(expr.tpl.exprs.len() + 1);
|
let mut exprs = Vec::with_capacity(expr.tpl.exprs.len() + 1);
|
||||||
exprs.push(expr.tag.take());
|
exprs.push(expr.tag.take());
|
||||||
@ -1318,9 +1379,17 @@ impl VisitMut for ReduceAst {
|
|||||||
|
|
||||||
fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
|
fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
|
||||||
if !self.collected_data {
|
if !self.collected_data {
|
||||||
let _timer = timer!("analyze before reducing");
|
|
||||||
self.collected_data = true;
|
self.collected_data = true;
|
||||||
self.data = Arc::new(ScopeData::analyze(&stmts));
|
|
||||||
|
{
|
||||||
|
let _timer = timer!("analyze before reducing");
|
||||||
|
self.data = Arc::new(ScopeData::analyze(&stmts));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let _timer = timer!("remove typescript nodes");
|
||||||
|
|
||||||
|
stmts.visit_mut_with(&mut ts_remover());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _timer = timer!("reduce ast (single pass)");
|
let _timer = timer!("reduce ast (single pass)");
|
||||||
@ -1438,7 +1507,12 @@ impl VisitMut for ReduceAst {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match pat {
|
match pat {
|
||||||
Pat::Assign(..) => {}
|
Pat::Assign(..) => {
|
||||||
|
let old = self.can_remove_pat;
|
||||||
|
self.can_remove_pat = false;
|
||||||
|
pat.visit_mut_children_with(self);
|
||||||
|
self.can_remove_pat = old;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
pat.visit_mut_children_with(self);
|
pat.visit_mut_children_with(self);
|
||||||
}
|
}
|
||||||
@ -1566,7 +1640,7 @@ impl VisitMut for ReduceAst {
|
|||||||
fn visit_mut_stmt(&mut self, stmt: &mut Stmt) {
|
fn visit_mut_stmt(&mut self, stmt: &mut Stmt) {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Debugger(_) | Stmt::Break(_) | Stmt::Continue(_) => {
|
Stmt::Debugger(_) | Stmt::Break(_) | Stmt::Continue(_) => {
|
||||||
*stmt = Stmt::Empty(EmptyStmt { span: stmt.span() });
|
*stmt = Stmt::Empty(EmptyStmt { span: DUMMY_SP });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
106
crates/swc_webpack_ast/src/reducer/typescript.rs
Normal file
106
crates/swc_webpack_ast/src/reducer/typescript.rs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
use swc_common::util::take::Take;
|
||||||
|
use swc_ecma_ast::*;
|
||||||
|
use swc_ecma_visit::{VisitMut, VisitMutWith};
|
||||||
|
|
||||||
|
pub fn ts_remover() -> impl VisitMut {
|
||||||
|
TsRemover {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TsRemover {}
|
||||||
|
|
||||||
|
impl VisitMut for TsRemover {
|
||||||
|
fn visit_mut_array_pat(&mut self, p: &mut ArrayPat) {
|
||||||
|
p.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
p.optional = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||||
|
e.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
match e {
|
||||||
|
Expr::TsAs(expr) => {
|
||||||
|
*e = *expr.expr.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr::TsConstAssertion(expr) => {
|
||||||
|
*e = *expr.expr.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr::TsTypeAssertion(expr) => {
|
||||||
|
*e = *expr.expr.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr::TsNonNull(expr) => {
|
||||||
|
*e = *expr.expr.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||||
|
i.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
i.optional = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_module_item(&mut self, s: &mut ModuleItem) {
|
||||||
|
s.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
match s {
|
||||||
|
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
|
||||||
|
decl: Decl::TsInterface(_) | Decl::TsTypeAlias(_),
|
||||||
|
..
|
||||||
|
}))
|
||||||
|
| ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
|
||||||
|
type_only: true, ..
|
||||||
|
}))
|
||||||
|
| ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
|
||||||
|
type_only: true,
|
||||||
|
..
|
||||||
|
})) => {
|
||||||
|
s.take();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_object_pat(&mut self, p: &mut ObjectPat) {
|
||||||
|
p.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
p.optional = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_opt_ts_type(&mut self, ty: &mut Option<Box<TsType>>) {
|
||||||
|
*ty = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_opt_ts_type_ann(&mut self, ty: &mut Option<TsTypeAnn>) {
|
||||||
|
*ty = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_opt_ts_type_param_decl(&mut self, t: &mut Option<TsTypeParamDecl>) {
|
||||||
|
*t = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_opt_ts_type_param_instantiation(
|
||||||
|
&mut self,
|
||||||
|
t: &mut Option<TsTypeParamInstantiation>,
|
||||||
|
) {
|
||||||
|
*t = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_stmt(&mut self, s: &mut Stmt) {
|
||||||
|
s.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
match s {
|
||||||
|
Stmt::Decl(Decl::TsTypeAlias(..) | Decl::TsInterface(..)) => {
|
||||||
|
s.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
use swc_common::{chain, Mark};
|
use swc_common::{chain, Mark, Span};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_parser::{EsConfig, Parser, StringInput, Syntax, TsConfig};
|
use swc_ecma_parser::{EsConfig, Parser, StringInput, Syntax, TsConfig};
|
||||||
use swc_ecma_transforms_base::resolver::resolver_with_mark;
|
use swc_ecma_transforms_base::resolver::resolver_with_mark;
|
||||||
@ -33,14 +33,24 @@ fn fixture(input: PathBuf) {
|
|||||||
struct AssertValid;
|
struct AssertValid;
|
||||||
|
|
||||||
impl VisitMut for AssertValid {
|
impl VisitMut for AssertValid {
|
||||||
|
fn visit_mut_array_pat(&mut self, a: &mut ArrayPat) {
|
||||||
|
if a.optional {
|
||||||
|
panic!("found an optional pattern: {:?}", a)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.visit_mut_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_mut_empty_stmt(&mut self, i: &mut EmptyStmt) {
|
fn visit_mut_empty_stmt(&mut self, i: &mut EmptyStmt) {
|
||||||
panic!("found empty: {:?}", i)
|
panic!("found empty: {:?}", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||||
if i.span.is_dummy() {
|
if i.optional {
|
||||||
panic!("found an identifier with dummy span: {:?}", i)
|
panic!("found an optional pattern: {:?}", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.visit_mut_children_with(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_mut_if_stmt(&mut self, s: &mut IfStmt) {
|
fn visit_mut_if_stmt(&mut self, s: &mut IfStmt) {
|
||||||
@ -59,11 +69,27 @@ impl VisitMut for AssertValid {
|
|||||||
fn visit_mut_module(&mut self, m: &mut Module) {
|
fn visit_mut_module(&mut self, m: &mut Module) {
|
||||||
dbg!(&*m);
|
dbg!(&*m);
|
||||||
|
|
||||||
m.visit_mut_children_with(self);
|
m.body.visit_mut_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_object_pat(&mut self, pat: &mut ObjectPat) {
|
||||||
|
if pat.optional {
|
||||||
|
panic!("found a optional pattern: {:?}", pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
pat.visit_mut_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_span(&mut self, sp: &mut Span) {
|
||||||
|
assert!(!sp.is_dummy());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_ts_type(&mut self, ty: &mut TsType) {
|
||||||
|
panic!("found a typescript type: {:?}", ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[testing::fixture("../swc_ecma_parser/tests/typescript/tsc/**/input.ts")]
|
#[testing::fixture("../swc_ecma_parser/tests/typescript/**/input.ts")]
|
||||||
#[testing::fixture("../swc/tests/tsc-references/**/output.js")]
|
#[testing::fixture("../swc/tests/tsc-references/**/output.js")]
|
||||||
fn assert_no_invalid(input: PathBuf) {
|
fn assert_no_invalid(input: PathBuf) {
|
||||||
testing::run_test(false, |cm, _handler| {
|
testing::run_test(false, |cm, _handler| {
|
||||||
|
@ -53,8 +53,7 @@ class Container extends React.Component {
|
|||||||
}
|
}
|
||||||
export const emitter = mitt();
|
export const emitter = mitt();
|
||||||
let CachedComponent;
|
let CachedComponent;
|
||||||
export async function initNext(opts = {
|
export async function initNext() {
|
||||||
}) {
|
|
||||||
let initialErr;
|
let initialErr;
|
||||||
const appEntrypoint = null;
|
const appEntrypoint = null;
|
||||||
const { component: app , exports: mod } = null;
|
const { component: app , exports: mod } = null;
|
||||||
|
@ -78,8 +78,7 @@ class Container {
|
|||||||
const emitter = null;
|
const emitter = null;
|
||||||
exports.emitter = null;
|
exports.emitter = null;
|
||||||
let CachedComponent;
|
let CachedComponent;
|
||||||
(function*(opts = {
|
(function*() {
|
||||||
}) {
|
|
||||||
let initialErr;
|
let initialErr;
|
||||||
const appEntrypoint = null;
|
const appEntrypoint = null;
|
||||||
const { component: app , exports: mod } = null;
|
const { component: app , exports: mod } = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user