Skip to content

Commit cdd9918

Browse files
committed
Merge remote-tracking branch 'origin/bugs'
2 parents 9133243 + b728e8d commit cdd9918

File tree

8 files changed

+127
-14
lines changed

8 files changed

+127
-14
lines changed

core/src/codegen.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ impl Code for Parameter {
333333
impl Code for Expression {
334334
fn to_code(&self, gen: &mut Generator) {
335335
match *self {
336+
Expression::Void => {},
336337

337338
Expression::This => gen.write_bytes(b"this"),
338339

@@ -381,6 +382,12 @@ impl Code for Expression {
381382
Expression::Array(ref items) => {
382383
gen.write_byte(b'[');
383384
gen.write_list(items);
385+
386+
// Add dangling comma if the array ends with a spare element
387+
if let Some(&Expression::Void) = items.iter().rev().next() {
388+
gen.write_byte(b',');
389+
}
390+
384391
gen.write_byte(b']');
385392
},
386393

core/src/grammar.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct Parameter {
2121

2222
#[derive(Debug, PartialEq, Clone)]
2323
pub enum Expression {
24+
Void,
2425
This,
2526
Identifier(OwnedSlice),
2627
Literal(Value),

core/src/parser.rs

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ impl<'a> Parser<'a> {
132132
loop {
133133
match next!(self) {
134134
BracketClose => break,
135+
Comma => {
136+
list.push(Expression::Void);
137+
continue;
138+
}
135139
token => {
136140
let expression = try!(self.expression_from_token(token, 0));
137141
list.push(expression);
@@ -566,7 +570,7 @@ impl<'a> Parser<'a> {
566570
},
567571

568572
ParenOpen => {
569-
if lbp > 0 {
573+
if lbp > 18 {
570574
break;
571575
}
572576

@@ -579,7 +583,7 @@ impl<'a> Parser<'a> {
579583
},
580584

581585
BracketOpen => {
582-
if lbp > 0 {
586+
if lbp > 19 {
583587
break;
584588
}
585589

@@ -616,6 +620,14 @@ impl<'a> Parser<'a> {
616620

617621
/// Helper for the `for` loops that doesn't consume semicolons
618622
fn variable_declaration(&mut self, kind: VariableDeclarationKind) -> Result<Statement> {
623+
Ok(Statement::VariableDeclaration {
624+
kind: kind,
625+
declarators: try!(self.variable_declarators()),
626+
})
627+
}
628+
629+
#[inline]
630+
fn variable_declarators(&mut self) -> Result<Vec<VariableDeclarator>> {
619631
let mut declarators = Vec::new();
620632

621633
loop {
@@ -636,10 +648,7 @@ impl<'a> Parser<'a> {
636648
break;
637649
}
638650

639-
Ok(Statement::VariableDeclaration {
640-
kind: kind,
641-
declarators: declarators,
642-
})
651+
Ok(declarators)
643652
}
644653

645654
#[inline]
@@ -799,9 +808,40 @@ impl<'a> Parser<'a> {
799808
let init = match next!(self) {
800809
Semicolon => None,
801810

802-
Declaration(kind) => Some(Box::new(try!(self.variable_declaration(kind)))),
811+
Declaration(kind) => {
812+
let mut declarators = try!(self.variable_declarators());
813+
814+
if declarators.len() == 1 {
815+
let value = declarators[0].value.take();
803816

804-
token => {
817+
match value {
818+
Some(Expression::Binary {
819+
operator: In,
820+
left,
821+
right,
822+
..
823+
}) => {
824+
declarators[0].value = Some(*left);
825+
826+
let left = Statement::VariableDeclaration {
827+
kind: kind,
828+
declarators: declarators,
829+
};
830+
831+
return self.for_in_statement_from_parts(left, *right);
832+
},
833+
834+
_ => declarators[0].value = value
835+
}
836+
}
837+
838+
Some(Box::new(Statement::VariableDeclaration {
839+
kind: kind,
840+
declarators: declarators,
841+
}))
842+
}
843+
844+
token => {
805845
let expression = try!(self.sequence_or_expression_from_token(token));
806846

807847
if let Expression::Binary {
@@ -810,7 +850,7 @@ impl<'a> Parser<'a> {
810850
right,
811851
..
812852
} = expression {
813-
return self.for_in_statement_from_expressions(*left, *right);
853+
return self.for_in_statement_from_parts(*left, *right);
814854
}
815855

816856
Some(Box::new(expression.into()))
@@ -858,8 +898,8 @@ impl<'a> Parser<'a> {
858898
})
859899
}
860900

861-
fn for_in_statement_from_expressions(&mut self, left: Expression, right: Expression)
862-
-> Result<Statement> {
901+
fn for_in_statement_from_parts<S>(&mut self, left: S, right: Expression) -> Result<Statement>
902+
where S: Into<Statement> {
863903
let left = Box::new(left.into());
864904

865905
expect!(self, ParenClose);

core/src/tokenizer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static BYTE_HANDLERS: [fn(&mut Tokenizer, u8) -> Result<Token>; 256] = [
4343
___, EXL, QOT, ___, IDT, PRC, AMP, QOT, PNO, PNC, ATR, PLS, COM, MIN, PRD, SLH, // 2
4444
ZER, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, COL, SEM, LSS, EQL, MOR, QST, // 3
4545
___, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, // 4
46-
IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, BTO, ___, BTC, CRT, IDT, // 5
46+
IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, IDT, BTO, IDT, BTC, CRT, IDT, // 5
4747
TPL, IDT, L_B, L_C, L_D, L_E, L_F, IDT, IDT, L_I, IDT, IDT, L_L, IDT, L_N, IDT, // 6
4848
L_P, IDT, L_R, L_S, L_T, L_U, L_V, L_W, IDT, L_Y, IDT, BEO, PIP, BEC, TLD, ___, // 7
4949
UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, // 8
@@ -829,6 +829,7 @@ mod ident_lookup {
829829
pub const DO: bool = true; // dollar sign $
830830
pub const US: bool = true; // underscore
831831
pub const UN: bool = true; // unicode
832+
pub const BS: bool = true; // backslash
832833
pub const __: bool = false;
833834

834835
pub static TABLE: [bool; 256] = [
@@ -838,7 +839,7 @@ mod ident_lookup {
838839
__, __, __, __, DO, __, __, __, __, __, __, __, __, __, __, __, // 2
839840
NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, __, __, __, __, __, __, // 3
840841
__, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, // 4
841-
AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, __, __, __, __, US, // 5
842+
AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, __, BS, __, __, US, // 5
842843
__, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, // 6
843844
AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, __, __, __, __, __, // 7
844845
UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, UN, // 8
@@ -1048,6 +1049,8 @@ impl<'a> Tokenizer<'a> {
10481049

10491050
#[inline]
10501051
fn consume_label_characters(&mut self) -> &str {
1052+
// TODO: Reject invalid unicode and escaped unicode character
1053+
10511054
let start = self.index;
10521055

10531056
self.bump();

core/src/transformer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ impl<T> Take for Vec<T> {
2929
impl Take for Expression {
3030
#[inline]
3131
fn take(&mut self) -> Self {
32-
mem::replace(self, Expression::This)
32+
mem::replace(self, Expression::Void)
3333
}
3434
}
3535

@@ -490,6 +490,7 @@ impl Transformable for Expression {
490490
return;
491491
},
492492

493+
Expression::Void |
493494
Expression::This |
494495
Expression::Literal(..) |
495496
Expression::RegEx {..} |

core/tests/codegen.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,14 @@ fn class_method_default_parameters() {
192192
fn try_catch() {
193193
assert_compile!("try{foo();}catch(err){console.error(err);}", "try{foo();}catch(err){console.error(err);}");
194194
}
195+
196+
#[test]
197+
fn ternary_expression() {
198+
assert_compile!("const a=1?console.log('foo'):null;", "var a=1?console.log('foo'):null;")
199+
}
200+
201+
#[test]
202+
fn sparse_array_expression() {
203+
assert_compile!("[,,1];", "[,,1];");
204+
assert_compile!("[,,];", "[,,];");
205+
}

core/tests/parser.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,25 @@ fn for_in_declare_statement() {
688688
});
689689
}
690690

691+
#[test]
692+
fn for_in_declare_statement_initial_value() {
693+
assert_statement!("for (let item = 0 in object) {}", Statement::ForIn {
694+
left: Box::new(Statement::VariableDeclaration {
695+
kind: VariableDeclarationKind::Let,
696+
declarators: vec![
697+
VariableDeclarator {
698+
name: "item".into(),
699+
value: Some(num!("0")),
700+
}
701+
],
702+
}),
703+
right: ident!("object"),
704+
body: Box::new(Statement::Block {
705+
body: Vec::new(),
706+
}),
707+
});
708+
}
709+
691710
#[test]
692711
fn for_in_declare_no_block_statement() {
693712
assert_statement!("for (let item in object);", Statement::ForIn {
@@ -748,6 +767,25 @@ fn for_of_declare_statement() {
748767
});
749768
}
750769

770+
#[test]
771+
fn for_of_declare_statement_initial_value() {
772+
assert_statement!("for (let item = 0 of array) {}", Statement::ForOf {
773+
left: Box::new(Statement::VariableDeclaration {
774+
kind: VariableDeclarationKind::Let,
775+
declarators: vec![
776+
VariableDeclarator {
777+
name: "item".into(),
778+
value: Some(num!("0")),
779+
}
780+
],
781+
}),
782+
right: ident!("array"),
783+
body: Box::new(Statement::Block {
784+
body: Vec::new(),
785+
}),
786+
});
787+
}
788+
751789
#[test]
752790
fn for_of_declare_no_block_statement() {
753791
assert_statement!("for (let item of array);", Statement::ForOf {

core/tests/tokenizer.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ macro_rules! assert_token {
3030
}
3131
}
3232

33+
#[test]
34+
fn test_tokenizer_identifier() {
35+
assert_token!("foo", Identifier("foo".into()), "read a plain identifier");
36+
assert_token!("_foo", Identifier("_foo".into()), "read an identifier starting with _");
37+
assert_token!("$foo", Identifier("$foo".into()), "read an identifier starting with $");
38+
assert_token!("_0", Identifier("_0".into()), "read an identifier with _ and digit");
39+
assert_token!("$0", Identifier("$0".into()), "read an identifier with $ and digit");
40+
assert_token!("π", Identifier("π".into()), "read a unicode identifier");
41+
assert_token!("\\u0050", Identifier("\\u0050".into()), "read an escaped unicode identifier");
42+
assert_token!("_\\u0050", Identifier("_\\u0050".into()), "read an identifier with escaped unicode character");
43+
}
44+
3345
#[test]
3446
fn test_tokenizer_chars() {
3547
assert_token!(";", Semicolon, "read a Semicolon");

0 commit comments

Comments
 (0)