Skip to content

Commit

Permalink
fix(es/parser) Throw a syntax error for const without initializer i…
Browse files Browse the repository at this point in the history
…n strict mode (#3742)

Co-authored-by: Donny/강동윤 <kdy1997.dev@gmail.com>
  • Loading branch information
williamtetlow and kdy1 committed Feb 27, 2022
1 parent 1865b6d commit abc0572
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/cargo.yml
Expand Up @@ -16,6 +16,8 @@ env:
CARGO_INCREMENTAL: 0
RUST_LOG: "debug"
DIFF: 0
# https://github.com/swc-project/swc/pull/3742
RUST_MIN_STACK: 4194304

jobs:
check-license:
Expand Down
2 changes: 0 additions & 2 deletions crates/swc_ecma_codegen/src/stmt.rs
Expand Up @@ -42,13 +42,11 @@ mod tests {
fn declaration_statement() {
assert_min("var foo;", "var foo");
assert_min("let foo;", "let foo");
assert_min("const foo;", "const foo");
assert_min("var foo = 10;", "var foo=10");
assert_min("let foo = 10;", "let foo=10");
assert_min("const foo = 10;", "const foo=10");
assert_min("var foo, bar;", "var foo,bar");
assert_min("let foo, bar;", "let foo,bar");
assert_min("const foo, bar;", "const foo,bar");
assert_min("var foo = 10, bar = 20;", "var foo=10,bar=20");
assert_min("let foo = 10, bar = 20;", "let foo=10,bar=20");
assert_min("const foo = 10, bar = 20;", "const foo=10,bar=20");
Expand Down
6 changes: 6 additions & 0 deletions crates/swc_ecma_parser/src/error.rs
Expand Up @@ -183,6 +183,8 @@ pub enum SyntaxError {
ImportBindingIsString(JsWord),
ExportBindingIsString,

ConstDeclarationsRequireInitialization,

TS1003,
TS1005,
TS1009,
Expand Down Expand Up @@ -487,6 +489,10 @@ impl SyntaxError {
"A string literal cannot be used as an exported binding without `from`.".into()
}

SyntaxError::ConstDeclarationsRequireInitialization => {
"'const' declarations must be initialized".into()
}

SyntaxError::TS1003 => "Expected an identifier".into(),
SyntaxError::TS1005 => "Expected a semicolon".into(),
SyntaxError::TS1009 => "Trailing comma is not allowed".into(),
Expand Down
47 changes: 45 additions & 2 deletions crates/swc_ecma_parser/src/parser/stmt.rs
Expand Up @@ -727,7 +727,7 @@ impl<'a, I: Tokens> Parser<I> {
break;
}

decls.push(self.with_ctx(ctx).parse_var_declarator(for_loop)?);
decls.push(self.with_ctx(ctx).parse_var_declarator(for_loop, kind)?);
}

if !for_loop && !eat!(self, ';') {
Expand All @@ -748,7 +748,11 @@ impl<'a, I: Tokens> Parser<I> {
})
}

fn parse_var_declarator(&mut self, for_loop: bool) -> PResult<VarDeclarator> {
fn parse_var_declarator(
&mut self,
for_loop: bool,
kind: VarDeclKind,
) -> PResult<VarDeclarator> {
let start = cur_pos!(self);

let mut name = self.parse_binding_pat_or_ident()?;
Expand Down Expand Up @@ -798,6 +802,13 @@ impl<'a, I: Tokens> Parser<I> {
// Destructuring bindings require initializers, but
// typescript allows `declare` vars not to have initializers.
if self.ctx().in_declare {
None
} else if kind == VarDeclKind::Const && self.ctx().strict {
self.emit_err(
span!(self, start),
SyntaxError::ConstDeclarationsRequireInitialization,
);

None
} else {
match name {
Expand Down Expand Up @@ -2214,4 +2225,36 @@ export default function waitUntil(callback, options = {}) {
let src = "export { 'foo' };";
test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module());
}

#[test]
#[should_panic(expected = "'const' declarations must be initialized")]
fn ts_error_for_const_declaration_not_initialized() {
let src = r#"
"use strict";
const foo;"#;

test_parser(
src,
Syntax::Typescript(TsConfig {
..Default::default()
}),
|p| p.parse_script(),
);
}

#[test]
#[should_panic(expected = "'const' declarations must be initialized")]
fn es_error_for_const_declaration_not_initialized() {
let src = r#"
"use strict";
const foo;"#;

test_parser(
src,
Syntax::Es(EsConfig {
..Default::default()
}),
|p| p.parse_script(),
);
}
}

1 comment on commit abc0572

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: abc0572 Previous: 6d98d14 Ratio
full_es2015 201847575 ns/iter (± 43197910) 186843502 ns/iter (± 15753059) 1.08
full_es2016 212218046 ns/iter (± 46761577) 192751066 ns/iter (± 22182654) 1.10
full_es2017 213611587 ns/iter (± 39076174) 192640468 ns/iter (± 10462314) 1.11
full_es2018 223953055 ns/iter (± 55072588) 194371664 ns/iter (± 22682621) 1.15
full_es2019 224508033 ns/iter (± 36166807) 189419396 ns/iter (± 13980042) 1.19
full_es2020 193961796 ns/iter (± 18082857) 168700284 ns/iter (± 10645551) 1.15
full_es3 267048863 ns/iter (± 23127226) 239732451 ns/iter (± 15580476) 1.11
full_es5 277268881 ns/iter (± 40634689) 235946386 ns/iter (± 14544796) 1.18
parser 897314 ns/iter (± 113527) 759032 ns/iter (± 106811) 1.18

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.