mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 17:54:15 +03:00
Bugs (#303)
swc_ecma_transforms: - report error if jsx namespace is used (#301)
This commit is contained in:
parent
a2144bbbf5
commit
1a0f1108a1
@ -205,7 +205,15 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
assert!(self.input.cur().unwrap().is_ident_start());
|
||||
|
||||
let cur_pos = self.input.cur_pos();
|
||||
let slice = self.input.uncons_while(|c| c.is_ident_part() || c == '-');
|
||||
let mut first = true;
|
||||
let slice = self.input.uncons_while(|c| {
|
||||
if first {
|
||||
first = false;
|
||||
c.is_ident_start()
|
||||
} else {
|
||||
c.is_ident_part() || c == '-'
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Token::JSXName { name: slice.into() })
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{drop_span, CM, SESSION},
|
||||
util::{
|
||||
drop_span,
|
||||
options::{CM, SESSION},
|
||||
},
|
||||
};
|
||||
use ast::*;
|
||||
use chashmap::CHashMap;
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::util::{prepend_stmts, DropSpan, CM, SESSION};
|
||||
use crate::util::{
|
||||
options::{CM, SESSION},
|
||||
prepend_stmts, DropSpan,
|
||||
};
|
||||
use ast::*;
|
||||
use scoped_tls::scoped_thread_local;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{drop_span, ExprFactory, CM, SESSION},
|
||||
util::{
|
||||
drop_span,
|
||||
options::{CM, SESSION},
|
||||
ExprFactory, HANDLER,
|
||||
},
|
||||
};
|
||||
use ast::*;
|
||||
use chashmap::CHashMap;
|
||||
@ -100,6 +104,7 @@ pub fn jsx(options: Options) -> impl Pass {
|
||||
expr: parse_option("pragmaFrag", options.pragma_frag),
|
||||
},
|
||||
use_builtins: options.use_builtins,
|
||||
throw_if_namespace: options.throw_if_namespace,
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,6 +112,7 @@ struct Jsx {
|
||||
pragma: ExprOrSuper,
|
||||
pragma_frag: ExprOrSpread,
|
||||
use_builtins: bool,
|
||||
throw_if_namespace: bool,
|
||||
}
|
||||
|
||||
impl Jsx {
|
||||
@ -133,7 +139,7 @@ impl Jsx {
|
||||
fn jsx_elem_to_expr(&mut self, el: JSXElement) -> Expr {
|
||||
let span = el.span();
|
||||
|
||||
let name = jsx_name(el.opening.name);
|
||||
let name = self.jsx_name(el.opening.name);
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
span,
|
||||
@ -278,60 +284,75 @@ impl Fold<Expr> for Jsx {
|
||||
}
|
||||
}
|
||||
|
||||
fn jsx_name(name: JSXElementName) -> Box<Expr> {
|
||||
let span = name.span();
|
||||
match name {
|
||||
JSXElementName::Ident(i) => {
|
||||
// If it starts with lowercase digit
|
||||
let c = i.sym.chars().next().unwrap();
|
||||
impl Jsx {
|
||||
fn jsx_name(&self, name: JSXElementName) -> Box<Expr> {
|
||||
let span = name.span();
|
||||
match name {
|
||||
JSXElementName::Ident(i) => {
|
||||
// If it starts with lowercase digit
|
||||
let c = i.sym.chars().next().unwrap();
|
||||
|
||||
if i.sym == js_word!("this") {
|
||||
return box Expr::This(ThisExpr { span });
|
||||
}
|
||||
if i.sym == js_word!("this") {
|
||||
return box Expr::This(ThisExpr { span });
|
||||
}
|
||||
|
||||
if c.is_ascii_lowercase() {
|
||||
box Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
value: i.sym,
|
||||
has_escape: false,
|
||||
}))
|
||||
} else {
|
||||
box Expr::Ident(i)
|
||||
}
|
||||
}
|
||||
JSXElementName::JSXNamespacedName(JSXNamespacedName { ref ns, ref name }) => {
|
||||
box Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
value: format!("{}:{}", ns.sym, name.sym).into(),
|
||||
has_escape: false,
|
||||
}))
|
||||
}
|
||||
JSXElementName::JSXMemberExpr(JSXMemberExpr { obj, prop }) => {
|
||||
fn convert_obj(obj: JSXObject) -> ExprOrSuper {
|
||||
let span = obj.span();
|
||||
|
||||
match obj {
|
||||
JSXObject::Ident(i) => {
|
||||
if i.sym == js_word!("this") {
|
||||
return ExprOrSuper::Expr(box Expr::This(ThisExpr { span }));
|
||||
}
|
||||
i.as_obj()
|
||||
}
|
||||
JSXObject::JSXMemberExpr(box JSXMemberExpr { obj, prop }) => MemberExpr {
|
||||
if c.is_ascii_lowercase() {
|
||||
box Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
obj: convert_obj(obj),
|
||||
prop: box Expr::Ident(prop),
|
||||
computed: false,
|
||||
}
|
||||
.as_obj(),
|
||||
value: i.sym,
|
||||
has_escape: false,
|
||||
}))
|
||||
} else {
|
||||
box Expr::Ident(i)
|
||||
}
|
||||
}
|
||||
box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: convert_obj(obj),
|
||||
prop: box Expr::Ident(prop),
|
||||
computed: false,
|
||||
})
|
||||
JSXElementName::JSXNamespacedName(JSXNamespacedName { ref ns, ref name }) => {
|
||||
if self.throw_if_namespace {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
span,
|
||||
"JSX Namespace is disabled by default because react does not \
|
||||
support it yet. You can specify \
|
||||
jsc.transform.react.throwIfNamespace to false to override \
|
||||
default behavior",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
box Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
value: format!("{}:{}", ns.sym, name.sym).into(),
|
||||
has_escape: false,
|
||||
}))
|
||||
}
|
||||
JSXElementName::JSXMemberExpr(JSXMemberExpr { obj, prop }) => {
|
||||
fn convert_obj(obj: JSXObject) -> ExprOrSuper {
|
||||
let span = obj.span();
|
||||
|
||||
match obj {
|
||||
JSXObject::Ident(i) => {
|
||||
if i.sym == js_word!("this") {
|
||||
return ExprOrSuper::Expr(box Expr::This(ThisExpr { span }));
|
||||
}
|
||||
i.as_obj()
|
||||
}
|
||||
JSXObject::JSXMemberExpr(box JSXMemberExpr { obj, prop }) => MemberExpr {
|
||||
span,
|
||||
obj: convert_obj(obj),
|
||||
prop: box Expr::Ident(prop),
|
||||
computed: false,
|
||||
}
|
||||
.as_obj(),
|
||||
}
|
||||
}
|
||||
box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: convert_obj(obj),
|
||||
prop: box Expr::Ident(prop),
|
||||
computed: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -645,7 +645,7 @@ React.createElement("div", {
|
||||
id: "w\xF4w"
|
||||
});
|
||||
React.createElement("div", {
|
||||
id: "\\w"
|
||||
id: "w"
|
||||
});
|
||||
React.createElement("div", {
|
||||
id: "w < w"
|
||||
|
@ -29,7 +29,9 @@ impl<'a> Tester<'a> {
|
||||
F: FnOnce(&mut Tester) -> Result<(), ()>,
|
||||
{
|
||||
let out = ::testing::run_test(false, |cm, handler| {
|
||||
HELPERS.set(&Default::default(), || op(&mut Tester { cm, handler }))
|
||||
crate::util::HANDLER.set(handler, || {
|
||||
HELPERS.set(&Default::default(), || op(&mut Tester { cm, handler }))
|
||||
})
|
||||
});
|
||||
|
||||
match out {
|
||||
|
@ -10,23 +10,22 @@ pub use self::{
|
||||
Purity::{MayBeImpure, Pure},
|
||||
};
|
||||
use ast::*;
|
||||
use scoped_tls::scoped_thread_local;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
f64::{INFINITY, NAN},
|
||||
num::FpCategory,
|
||||
ops::Add,
|
||||
sync::Arc,
|
||||
};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{
|
||||
errors::{ColorConfig, Handler},
|
||||
FilePathMapping, Fold, FoldWith, Mark, SourceMap, Span, Spanned, Visit, VisitWith, DUMMY_SP,
|
||||
errors::Handler, Fold, FoldWith, Mark, Span, Spanned, Visit, VisitWith, DUMMY_SP,
|
||||
};
|
||||
use swc_ecma_parser::Session;
|
||||
use unicode_xid::UnicodeXID;
|
||||
|
||||
pub(crate) mod constructor;
|
||||
mod factory;
|
||||
pub(crate) mod options;
|
||||
mod value;
|
||||
pub(crate) mod var;
|
||||
|
||||
@ -1015,10 +1014,4 @@ impl<'a> UsageFinder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub(crate) static ref CM: Arc<SourceMap> =
|
||||
{ Arc::new(SourceMap::new(FilePathMapping::empty())) };
|
||||
pub(crate) static ref HANDLER: Handler =
|
||||
{ Handler::with_tty_emitter(ColorConfig::Always, false, true, Some(CM.clone())) };
|
||||
pub(crate) static ref SESSION: Session<'static> = { Session { handler: &*HANDLER } };
|
||||
}
|
||||
scoped_thread_local!(pub static HANDLER: Handler);
|
||||
|
14
ecmascript/transforms/src/util/options.rs
Normal file
14
ecmascript/transforms/src/util/options.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use swc_common::{
|
||||
errors::{ColorConfig, Handler},
|
||||
FilePathMapping, SourceMap,
|
||||
};
|
||||
use swc_ecma_parser::Session;
|
||||
|
||||
lazy_static! {
|
||||
pub(crate) static ref CM: Arc<SourceMap> =
|
||||
{ Arc::new(SourceMap::new(FilePathMapping::empty())) };
|
||||
pub(crate) static ref HANDLER: Handler =
|
||||
{ Handler::with_tty_emitter(ColorConfig::Always, false, true, Some(CM.clone())) };
|
||||
pub(crate) static ref SESSION: Session<'static> = { Session { handler: &*HANDLER } };
|
||||
}
|
@ -42,6 +42,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_test2<F, Ret>(treat_err_as_bug: bool, op: F) -> Result<Ret, StdErr>
|
||||
where
|
||||
F: FnOnce(Arc<SourceMap>, Handler) -> Result<Ret, ()>,
|
||||
{
|
||||
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let (handler, errors) = self::errors::new_handler(cm.clone(), treat_err_as_bug);
|
||||
let result = swc_common::GLOBALS.set(&swc_common::Globals::new(), || op(cm, handler));
|
||||
|
||||
match result {
|
||||
Ok(res) => Ok(res),
|
||||
Err(()) => Err(errors.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove all span from `t`.
|
||||
pub fn drop_span<T>(t: T) -> T
|
||||
where
|
||||
|
Loading…
Reference in New Issue
Block a user