mirror of
https://github.com/swc-project/swc.git
synced 2024-10-05 04:39:06 +03:00
fix(es): Fix easy bugs (#2178)
swc_ecma_parser: - Fix parsing of complex arrow expressions in a conditional expression. (#2174) - Report an error for wrong jsx, instead of `panic!`. (#2173) swc_ecma_transforms_react: - `jsx`: Handle fragment with single child correctly. (#2177) swc: - Ensure that #2170 is an invalid issue. (#2170)
This commit is contained in:
parent
a10118c90f
commit
c0b0337d1d
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -2287,7 +2287,7 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
||||
|
||||
[[package]]
|
||||
name = "swc"
|
||||
version = "0.47.0"
|
||||
version = "0.46.1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
@ -2660,7 +2660,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.68.0"
|
||||
version = "0.68.1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"enum_kind",
|
||||
@ -2876,7 +2876,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_react"
|
||||
version = "0.36.0"
|
||||
version = "0.36.1"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"dashmap",
|
||||
|
@ -20,7 +20,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.47.0"
|
||||
version = "0.46.1"
|
||||
|
||||
[lib]
|
||||
name = "swc"
|
||||
|
@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"]
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_ecma_parser"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.68.0"
|
||||
version = "0.68.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
@ -409,6 +409,7 @@ pub struct Context {
|
||||
|
||||
/// If true, `:` should not be treated as a type annotation.
|
||||
in_cond_expr: bool,
|
||||
is_direct_child_of_cond: bool,
|
||||
|
||||
in_function: bool,
|
||||
|
||||
|
@ -80,18 +80,21 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
&& (is_one_of!(self, '<', JSXTagStart))
|
||||
&& (peeked_is!(self, IdentName) || peeked_is!(self, JSXName))
|
||||
{
|
||||
let res = self.try_parse_ts(|p| {
|
||||
let ctx = Context {
|
||||
is_direct_child_of_cond: false,
|
||||
..self.ctx()
|
||||
};
|
||||
let res = self.with_ctx(ctx).try_parse_ts(|p| {
|
||||
if is!(p, JSXTagStart) {
|
||||
debug_assert_eq!(
|
||||
p.input.token_context().current(),
|
||||
Some(TokenContext::JSXOpeningTag)
|
||||
);
|
||||
p.input.token_context_mut().pop();
|
||||
debug_assert_eq!(
|
||||
p.input.token_context().current(),
|
||||
Some(TokenContext::JSXExpr)
|
||||
);
|
||||
p.input.token_context_mut().pop();
|
||||
if let Some(TokenContext::JSXOpeningTag) = p.input.token_context().current() {
|
||||
p.input.token_context_mut().pop();
|
||||
|
||||
debug_assert_eq!(
|
||||
p.input.token_context().current(),
|
||||
Some(TokenContext::JSXExpr)
|
||||
);
|
||||
p.input.token_context_mut().pop();
|
||||
}
|
||||
}
|
||||
|
||||
let type_parameters = p.parse_ts_type_params()?;
|
||||
@ -197,6 +200,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
if eat!(self, '?') {
|
||||
let ctx = Context {
|
||||
in_cond_expr: true,
|
||||
is_direct_child_of_cond: true,
|
||||
include_in_expr: true,
|
||||
..self.ctx()
|
||||
};
|
||||
@ -204,6 +208,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
expect!(self, ':');
|
||||
let ctx = Context {
|
||||
in_cond_expr: true,
|
||||
is_direct_child_of_cond: true,
|
||||
..self.ctx()
|
||||
};
|
||||
let alt = self.with_ctx(ctx).parse_assignment_expr()?;
|
||||
@ -550,36 +555,43 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
pub(super) fn parse_args(&mut self, is_dynamic_import: bool) -> PResult<Vec<ExprOrSpread>> {
|
||||
trace_cur!(self, parse_args);
|
||||
|
||||
let start = cur_pos!(self);
|
||||
expect!(self, '(');
|
||||
let ctx = Context {
|
||||
is_direct_child_of_cond: false,
|
||||
..self.ctx()
|
||||
};
|
||||
|
||||
let mut first = true;
|
||||
let mut expr_or_spreads = vec![];
|
||||
self.with_ctx(ctx).parse_with(|p| {
|
||||
let start = cur_pos!(p);
|
||||
expect!(p, '(');
|
||||
|
||||
while !eof!(self) && !is!(self, ')') {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
expect!(self, ',');
|
||||
// Handle trailing comma.
|
||||
if is!(self, ')') {
|
||||
if is_dynamic_import {
|
||||
syntax_error!(
|
||||
self,
|
||||
span!(self, start),
|
||||
SyntaxError::TrailingCommaInsideImport
|
||||
)
|
||||
let mut first = true;
|
||||
let mut expr_or_spreads = vec![];
|
||||
|
||||
while !eof!(p) && !is!(p, ')') {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
expect!(p, ',');
|
||||
// Handle trailing comma.
|
||||
if is!(p, ')') {
|
||||
if is_dynamic_import {
|
||||
syntax_error!(
|
||||
p,
|
||||
span!(p, start),
|
||||
SyntaxError::TrailingCommaInsideImport
|
||||
)
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
expr_or_spreads.push(p.include_in_expr(true).parse_expr_or_spread()?);
|
||||
}
|
||||
|
||||
expr_or_spreads.push(self.include_in_expr(true).parse_expr_or_spread()?);
|
||||
}
|
||||
|
||||
expect!(self, ')');
|
||||
Ok(expr_or_spreads)
|
||||
expect!(p, ')');
|
||||
Ok(expr_or_spreads)
|
||||
})
|
||||
}
|
||||
|
||||
/// AssignmentExpression[+In, ?Yield, ?Await]
|
||||
@ -615,12 +627,21 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
// But as all patterns of javascript is subset of
|
||||
// expressions, we can parse both as expression.
|
||||
|
||||
let paren_items = self.include_in_expr(true).parse_args_or_pats()?;
|
||||
let ctx = Context {
|
||||
is_direct_child_of_cond: false,
|
||||
..self.ctx()
|
||||
};
|
||||
let paren_items = self
|
||||
.with_ctx(ctx)
|
||||
.include_in_expr(true)
|
||||
.parse_args_or_pats()?;
|
||||
let has_pattern = paren_items.iter().any(|item| match item {
|
||||
PatOrExprOrSpread::Pat(..) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let is_direct_child_of_cond = self.ctx().is_direct_child_of_cond;
|
||||
|
||||
// This is slow path. We handle arrow in conditional expression.
|
||||
if self.syntax().typescript() && self.ctx().in_cond_expr && is!(self, ':') {
|
||||
// TODO: Remove clone
|
||||
@ -637,6 +658,13 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
|
||||
let body: BlockStmtOrExpr = p.parse_fn_body(async_span.is_some(), false)?;
|
||||
|
||||
if is_direct_child_of_cond {
|
||||
if !is_one_of!(p, ':', ';') {
|
||||
trace_cur!(p, parse_arrow_in_cond__fail);
|
||||
unexpected!(p, "fail")
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(Box::new(Expr::Arrow(ArrowExpr {
|
||||
span: span!(p, expr_start),
|
||||
is_async: async_span.is_some(),
|
||||
@ -1308,6 +1336,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
let test = arg.expr;
|
||||
let ctx = Context {
|
||||
in_cond_expr: true,
|
||||
is_direct_child_of_cond: true,
|
||||
include_in_expr: true,
|
||||
..self.ctx()
|
||||
};
|
||||
@ -1315,6 +1344,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
expect!(self, ':');
|
||||
let ctx = Context {
|
||||
in_cond_expr: true,
|
||||
is_direct_child_of_cond: true,
|
||||
..self.ctx()
|
||||
};
|
||||
let alt = self.with_ctx(ctx).parse_assignment_expr()?;
|
||||
|
@ -0,0 +1,5 @@
|
||||
const setAction = (fields) =>
|
||||
setCurrentAction({
|
||||
...(<HeaderAction>getCurrentAction()),
|
||||
...fields,
|
||||
});
|
@ -0,0 +1,6 @@
|
||||
error: Unexpected token `HeaderAction`. Expected jsx identifier
|
||||
--> $DIR/tests/typescript-errors/issue-2173/case1/input.tsx:3:14
|
||||
|
|
||||
3 | ...(<HeaderAction>getCurrentAction()),
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -193,6 +193,7 @@ where
|
||||
}
|
||||
|
||||
#[testing::fixture("tests/typescript-errors/**/*.ts")]
|
||||
#[testing::fixture("tests/typescript-errors/**/*.tsx")]
|
||||
fn errors(file: PathBuf) {
|
||||
let file_name = file.display().to_string();
|
||||
|
||||
|
2164
ecmascript/parser/tests/typescript/deno/dso/reflect/input.ts
Normal file
2164
ecmascript/parser/tests/typescript/deno/dso/reflect/input.ts
Normal file
File diff suppressed because it is too large
Load Diff
54797
ecmascript/parser/tests/typescript/deno/dso/reflect/input.ts.json
Normal file
54797
ecmascript/parser/tests/typescript/deno/dso/reflect/input.ts.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
const x = {
|
||||
prop: isCorrect
|
||||
? fn => ({ })
|
||||
: fn => true,
|
||||
};
|
@ -0,0 +1,160 @@
|
||||
{
|
||||
"type": "Script",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 82,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 82,
|
||||
"ctxt": 0
|
||||
},
|
||||
"kind": "const",
|
||||
"declare": false,
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 81,
|
||||
"ctxt": 0
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 7,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "x",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
},
|
||||
"init": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 10,
|
||||
"end": 81,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "KeyValueProperty",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 16,
|
||||
"end": 20,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "prop",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "ConditionalExpression",
|
||||
"span": {
|
||||
"start": 22,
|
||||
"end": 78,
|
||||
"ctxt": 0
|
||||
},
|
||||
"test": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 22,
|
||||
"end": 31,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "isCorrect",
|
||||
"optional": false
|
||||
},
|
||||
"consequent": {
|
||||
"type": "ArrowFunctionExpression",
|
||||
"span": {
|
||||
"start": 42,
|
||||
"end": 53,
|
||||
"ctxt": 0
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 42,
|
||||
"end": 44,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "fn",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "ParenthesisExpression",
|
||||
"span": {
|
||||
"start": 48,
|
||||
"end": 53,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 49,
|
||||
"end": 52,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": []
|
||||
}
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"typeParameters": null,
|
||||
"returnType": null
|
||||
},
|
||||
"alternate": {
|
||||
"type": "ArrowFunctionExpression",
|
||||
"span": {
|
||||
"start": 68,
|
||||
"end": 78,
|
||||
"ctxt": 0
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 68,
|
||||
"end": 70,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "fn",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BooleanLiteral",
|
||||
"span": {
|
||||
"start": 74,
|
||||
"end": 78,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": true
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"typeParameters": null,
|
||||
"returnType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"definite": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
const x = {
|
||||
prop: isCorrect
|
||||
? fn => ({ })
|
||||
: fn => true,
|
||||
};
|
@ -0,0 +1,160 @@
|
||||
{
|
||||
"type": "Script",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 82,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 82,
|
||||
"ctxt": 0
|
||||
},
|
||||
"kind": "const",
|
||||
"declare": false,
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 81,
|
||||
"ctxt": 0
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 7,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "x",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
},
|
||||
"init": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 10,
|
||||
"end": 81,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "KeyValueProperty",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 16,
|
||||
"end": 20,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "prop",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "ConditionalExpression",
|
||||
"span": {
|
||||
"start": 22,
|
||||
"end": 78,
|
||||
"ctxt": 0
|
||||
},
|
||||
"test": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 22,
|
||||
"end": 31,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "isCorrect",
|
||||
"optional": false
|
||||
},
|
||||
"consequent": {
|
||||
"type": "ArrowFunctionExpression",
|
||||
"span": {
|
||||
"start": 42,
|
||||
"end": 53,
|
||||
"ctxt": 0
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 42,
|
||||
"end": 44,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "fn",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "ParenthesisExpression",
|
||||
"span": {
|
||||
"start": 48,
|
||||
"end": 53,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 49,
|
||||
"end": 52,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": []
|
||||
}
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"typeParameters": null,
|
||||
"returnType": null
|
||||
},
|
||||
"alternate": {
|
||||
"type": "ArrowFunctionExpression",
|
||||
"span": {
|
||||
"start": 68,
|
||||
"end": 78,
|
||||
"ctxt": 0
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 68,
|
||||
"end": 70,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "fn",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BooleanLiteral",
|
||||
"span": {
|
||||
"start": 74,
|
||||
"end": 78,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": true
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"typeParameters": null,
|
||||
"returnType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"definite": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_ecma_transforms_react"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.36.0"
|
||||
version = "0.36.1"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
@ -245,18 +245,7 @@ where
|
||||
|
||||
match children.len() {
|
||||
0 => {}
|
||||
1 if children[0].as_ref().unwrap().spread.is_none()
|
||||
&& match &*children[0].as_ref().unwrap().expr {
|
||||
Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(callee),
|
||||
..
|
||||
}) => match &**callee {
|
||||
Expr::Ident(Ident { sym, .. }) => *sym != *"_jsx",
|
||||
_ => true,
|
||||
},
|
||||
_ => true,
|
||||
} =>
|
||||
{
|
||||
1 if children[0].as_ref().unwrap().spread.is_none() => {
|
||||
props_obj
|
||||
.props
|
||||
.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
|
@ -0,0 +1,7 @@
|
||||
export var App = function () {
|
||||
return (
|
||||
<>
|
||||
<div>1</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"runtime": "automatic"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
||||
export var App = function() {
|
||||
return _jsx(_Fragment, {
|
||||
children: _jsx("div", {
|
||||
children: "1"
|
||||
})
|
||||
});
|
||||
};
|
@ -1,7 +1,5 @@
|
||||
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
||||
var x = _jsx(_Fragment, {
|
||||
children: [
|
||||
_jsx("div", {
|
||||
})
|
||||
]
|
||||
children: _jsx("div", {
|
||||
})
|
||||
});
|
||||
|
1
tests/fixture/issue-2170/case1/input/index.js
Normal file
1
tests/fixture/issue-2170/case1/input/index.js
Normal file
@ -0,0 +1 @@
|
||||
function foo(arg1 = 1, arg2 = 1) { }
|
3
tests/fixture/issue-2170/case1/output/index.js
Normal file
3
tests/fixture/issue-2170/case1/output/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
function foo(param, param1) {
|
||||
var arg1 = param === void 0 ? 1 : param, arg2 = param1 === void 0 ? 1 : param1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user