mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 17:54:15 +03:00
fix(es): Consume surrogate pairs (#4115)
This commit is contained in:
parent
13e7b4f92a
commit
fcf67c4570
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{D800}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{D800}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{D800}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{D800}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{DC00}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{DC00}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{DC00}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{DC00}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = `\u{D800}`;
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{D800}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = `\u{D800}`;
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu1 be floor((cp – 65536) / 1024) + 0xD800.
|
||||
// Although we should just get back a single code point value of 0xD800,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{D800}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = `\u{DC00}`;
|
@ -0,0 +1,6 @@
|
||||
// @target: es5
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{DC00}";
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = `\u{DC00}`;
|
@ -0,0 +1,6 @@
|
||||
// @target: es6
|
||||
// ES6 Spec - 10.1.1 Static Semantics: UTF16Encoding (cp)
|
||||
// 2. Let cu2 be ((cp – 65536) modulo 1024) + 0xDC00.
|
||||
// Although we should just get back a single code point value of 0xDC00,
|
||||
// this is a useful edge-case test.
|
||||
var x = "\u{DC00}";
|
@ -3324,23 +3324,38 @@ fn get_quoted_utf16(v: &str, target: EsVersion) -> String {
|
||||
|
||||
match next {
|
||||
// TODO fix me - workaround for surrogate pairs
|
||||
Some('\x00') => {
|
||||
Some('u') => {
|
||||
let mut inner_iter = iter.clone();
|
||||
|
||||
inner_iter.next();
|
||||
|
||||
let next = inner_iter.peek();
|
||||
let mut is_curly = false;
|
||||
let mut next = inner_iter.peek();
|
||||
|
||||
if next == Some(&'{') {
|
||||
is_curly = true;
|
||||
|
||||
if let Some('u') = next {
|
||||
inner_iter.next();
|
||||
next = inner_iter.peek();
|
||||
}
|
||||
|
||||
let mut is_valid = true;
|
||||
if let Some(c @ 'D' | c @ 'd') = next {
|
||||
let mut inner_buf = String::new();
|
||||
|
||||
inner_buf.push('\\');
|
||||
inner_buf.push('u');
|
||||
|
||||
for _ in 0..4 {
|
||||
if is_curly {
|
||||
inner_buf.push('{');
|
||||
}
|
||||
|
||||
inner_buf.push(*c);
|
||||
|
||||
inner_iter.next();
|
||||
|
||||
let mut is_valid = true;
|
||||
|
||||
for _ in 0..3 {
|
||||
let c = inner_iter.next();
|
||||
|
||||
match c {
|
||||
@ -3355,13 +3370,21 @@ fn get_quoted_utf16(v: &str, target: EsVersion) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
if is_curly {
|
||||
inner_buf.push('}');
|
||||
}
|
||||
|
||||
if is_valid {
|
||||
buf.push_str(&inner_buf);
|
||||
|
||||
for _ in 0..6 {
|
||||
let end = if is_curly { 7 } else { 5 };
|
||||
|
||||
for _ in 0..end {
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buf.push_str("\\\\");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -98,15 +98,29 @@ const string90 = new RegExp(" ").test(" ");
|
||||
const string91 = new RegExp("\x1b").test("[" + "\x1b" + "]");
|
||||
const string92 = new RegExp("\\x1b").test("\x1b");
|
||||
const string93 = new RegExp("").test("");
|
||||
const string94 = '';
|
||||
const string95 = 'ퟻ';
|
||||
const string94 = "";
|
||||
const string95 = "ퟻ";
|
||||
const string96 = sql`'#ERROR'`;
|
||||
const string97 = '\u{a0}';
|
||||
const string97 = "\u{a0}";
|
||||
const string98 = "\ud83d\ude00";
|
||||
const string99 = "\ud83d@\ude00";
|
||||
const string100 = "\a";
|
||||
const string101 = "
";
|
||||
// const string97 = '\u{D800}';
|
||||
// const string97 = '\u{DBFF}';
|
||||
// const string98 = '\u{DC00}';
|
||||
// const string99 = '\u{DFFF}';
|
||||
const string102 = "\uD800";
|
||||
const string103 = "\u{D800}";
|
||||
const string104 = "\uDBFF";
|
||||
const string105 = "\u{DBFF}";
|
||||
const string106 = "\uDC00";
|
||||
const string107 = "\u{DC00}";
|
||||
const string108 = "\uDFFF";
|
||||
const string109 = "\u{DFFF}";
|
||||
const string110 = "\uFFFF";
|
||||
const string111 = "\u{FFFF}";
|
||||
const string112 = "\ud800";
|
||||
const string113 = "\uD800";
|
||||
React.createElement("div", null, "this should not parse as unicode: \\u00a0");
|
||||
const a = "\u0591-\u06ef\u06fa-\u08ff\u200f\ud802-\ud803\ud83a-\ud83b\ufb1d-\ufdff\ufe70-\ufefc";
|
||||
const b = "A-Za-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02b8\u0300-\u0590\u0900-\u1fff\u200e\u2c00-\ud801\ud804-\ud839\ud83c-\udbff\uf900-\ufb1c\ufe00-\ufe6f\ufefd-\uffff";
|
||||
var x = "\u{D800}";
|
||||
var x2 = "\u{D800}";
|
||||
var x3 = "\u{D800}\u{D800}";
|
@ -98,11 +98,29 @@ const string90 = new RegExp(" ").test(" ");
|
||||
const string91 = new RegExp("\x1b").test("[" + "\x1b" + "]");
|
||||
const string92 = new RegExp("\\x1b").test("\x1b");
|
||||
const string93 = new RegExp("").test("");
|
||||
const string94 = '';
|
||||
const string95 = 'ퟻ';
|
||||
const string94 = "";
|
||||
const string95 = "ퟻ";
|
||||
const string96 = sql`'#ERROR'`;
|
||||
const string97 = '\u{a0}';
|
||||
const string97 = "\u{a0}";
|
||||
const string98 = "\ud83d\ude00";
|
||||
const string99 = "\ud83d@\ude00";
|
||||
const string100 = "\a";
|
||||
const string101 = "
";
|
||||
const string102 = "\uD800";
|
||||
const string103 = "\u{D800}";
|
||||
const string104 = "\uDBFF";
|
||||
const string105 = "\u{DBFF}";
|
||||
const string106 = "\uDC00";
|
||||
const string107 = "\u{DC00}";
|
||||
const string108 = "\uDFFF";
|
||||
const string109 = "\u{DFFF}";
|
||||
const string110 = "\uFFFF";
|
||||
const string111 = "\u{FFFF}";
|
||||
const string112 = "\ud800";
|
||||
const string113 = "\uD800";
|
||||
React.createElement("div", null, "this should not parse as unicode: \\u00a0");
|
||||
const a = "\u0591-\u06ef\u06fa-\u08ff\u200f\ud802-\ud803\ud83a-\ud83b\ufb1d-\ufdff\ufe70-\ufefc";
|
||||
const b = "A-Za-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02b8\u0300-\u0590\u0900-\u1fff\u200e\u2c00-\ud801\ud804-\ud839\ud83c-\udbff\uf900-\ufb1c\ufe00-\ufe6f\ufefd-\uffff";
|
||||
var x = "\u{D800}";
|
||||
var x2 = "\u{D800}";
|
||||
var x3 = "\u{D800}\u{D800}";
|
||||
|
@ -1,3 +1,3 @@
|
||||
const string1="test";const string2="test";const string3='te"st';const string4="te'st";const string5="test\ntest\ntest";const string6=`Yet another string primitive`;const string7="This is a very long string which needs to wrap across multiple lines because otherwise my code is unreadable.";const string8="\u4E2D\u6587 espa\xf1ol English \u0939\u093F\u0928\u094D\u0926\u0940 \u0627\u0644\u0639\u0631\u0628\u064A\u0629 portugu\xeas \u09AC\u09BE\u0982\u09B2\u09BE \u0440\u0443\u0441\u0441\u043A\u0438\u0439 \u65E5\u672C\u8A9E \u0A2A\u0A70\u0A1C\u0A3E\u0A2C\u0A40 \uD55C\uAD6D\uC5B4 \u0BA4\u0BAE\u0BBF\u0BB4\u0BCD";const string9=``;const string10=`xx\`x`;const string11=`${foo+2}`;const string12=` foo ${bar+`baz ${qux}`}`;const string13=String.raw`foo`;const string14=foo`bar`;const string15=`foo
|
||||
bar
|
||||
ↂωↂ`;const string16=`\``;const string17=`${4+4} equals 4 + 4`;const string18=`This is ${undefined}`;const string19=`This is ${NaN}`;const string20=`This is ${null}`;const string21=`This is ${Infinity}`;const string22="This is ${1/0}";const string23="This is ${1/0}";const string24="This is ${NaN}";const string25="This is ${null}";const string26=`This is ${1/0}`;const string27=`This is ${0/0}`;const string28="This is ${0/0}";const string29="This is ${0/0}";const string30=`${4**11}`;const string31=`${4**12}`;const string32=`${4**14}`;const string33="";const string34="\b";const string35="\f";const string36=" ";const string37="\v";const string38="\n";const string39="\\n";const string40="\\";const string41='\\"';const string42="'\"";const string43="\\\\";const string44="\0";const string45="\0!";const string46="\x001";const string47="\\0";const string48="\\0!";const string49="\x07";const string50="\x07!";const string51="\x071";const string52="\x07";const string53="\\7";const string54="\\7!";const string55="\\01";const string56="\x10";const string57="\\x10";const string58="\x1b";const string59="\\x1B";const string60="\uABCD";const string61="\uABCD";const string62="U000123AB";const string63="\u{123AB}";const string64="\ud808\udfab";const string65="\ud808";const string66="\ud808X";const string67="\udfab";const string68="\udfabX";const string69="\x80";const string70="\xff";const string71="\xf0\x9f\x8d\x95";const string72="\ud801\udc02\udc03\ud804";const string73="\u03C0";const 貓="\u{1F408}";const 貓abc="\u{1F408}";const abc貓="\u{1F408}";const string74="\u2028";const string75="\u2029";const string76="\uFEFF";const string77="\x10";const string78=" ";const string79=" ";const string80="2";const string81="\x16";const string82="\x06";const string83="\0a";const string84='"test"test"test';const string85="\"test'test'test";const string86='"test"test"test';const string87="'test'test'test";const string88="\u{1F604}";const string89=new RegExp("\r").test("\r");const string90=new RegExp(" ").test(" ");const string91=new RegExp("\x1b").test("["+"\x1b"+"]");const string92=new RegExp("\\x1b").test("\x1b");const string93=new RegExp("\x1b").test("\x1b");const string94="\uD7FF";const string95="\uD7FB";const string96=sql`'#ERROR'`;const string97="\xa0";const string98="\ud83d\ude00";const string99="\ud83d@\ude00";const string100="a";const string101="\u2028"
|
||||
ↂωↂ`;const string16=`\``;const string17=`${4+4} equals 4 + 4`;const string18=`This is ${undefined}`;const string19=`This is ${NaN}`;const string20=`This is ${null}`;const string21=`This is ${Infinity}`;const string22="This is ${1/0}";const string23="This is ${1/0}";const string24="This is ${NaN}";const string25="This is ${null}";const string26=`This is ${1/0}`;const string27=`This is ${0/0}`;const string28="This is ${0/0}";const string29="This is ${0/0}";const string30=`${4**11}`;const string31=`${4**12}`;const string32=`${4**14}`;const string33="";const string34="\b";const string35="\f";const string36=" ";const string37="\v";const string38="\n";const string39="\\n";const string40="\\";const string41='\\"';const string42="'\"";const string43="\\\\";const string44="\0";const string45="\0!";const string46="\x001";const string47="\\0";const string48="\\0!";const string49="\x07";const string50="\x07!";const string51="\x071";const string52="\x07";const string53="\\7";const string54="\\7!";const string55="\\01";const string56="\x10";const string57="\\x10";const string58="\x1b";const string59="\\x1B";const string60="\uABCD";const string61="\uABCD";const string62="U000123AB";const string63="\u{123AB}";const string64="\uD808\uDFAB";const string65="\uD808";const string66="\uD808X";const string67="\uDFAB";const string68="\uDFABX";const string69="\x80";const string70="\xff";const string71="\xf0\x9f\x8d\x95";const string72="\uD801\uDC02\uDC03\uD804";const string73="\u03C0";const 貓="\u{1F408}";const 貓abc="\u{1F408}";const abc貓="\u{1F408}";const string74="\u2028";const string75="\u2029";const string76="\uFEFF";const string77="\x10";const string78=" ";const string79=" ";const string80="2";const string81="\x16";const string82="\x06";const string83="\0a";const string84='"test"test"test';const string85="\"test'test'test";const string86='"test"test"test';const string87="'test'test'test";const string88="\u{1F604}";const string89=new RegExp("\r").test("\r");const string90=new RegExp(" ").test(" ");const string91=new RegExp("\x1b").test("["+"\x1b"+"]");const string92=new RegExp("\\x1b").test("\x1b");const string93=new RegExp("\x1b").test("\x1b");const string94="\uD7FF";const string95="\uD7FB";const string96=sql`'#ERROR'`;const string97="\xa0";const string98="\ud83d\ude00";const string99="\ud83d@\ude00";const string100="a";const string101="\u2028";const string102="\uD800";const string103="\u{D800}";const string104="\uDBFF";const string105="\u{DBFF}";const string106="\uDC00";const string107="\u{DC00}";const string108="\uDFFF";const string109="\u{DFFF}";const string110="\uFFFF";const string111="\uFFFF";const string112="\ud800";const string113="\uD800";React.createElement("div",null,"this should not parse as unicode: \\u00a0");const a="\u0591-\u06EF\u06FA-\u08FF\u200F\ud802-\ud803\ud83a-\ud83b\uFB1D-\uFDFF\uFE70-\uFEFC";const b="A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02B8\u0300-\u0590\u0900-\u1FFF\u200E\u2C00-\ud801\ud804-\ud839\ud83c-\udbff\uF900-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF";var x="\u{D800}";var x2="\u{D800}";var x3="\u{D800}\u{D800}"
|
||||
|
Binary file not shown.
Binary file not shown.
@ -12,4 +12,4 @@ test\u2028
|
||||
test\u2029
|
||||
test\xa7
|
||||
test
|
||||
`;const template_literal103=`\0z`;const template_literal104=`\0`;const template_literal105=`x``x`;const template_literal106=`😀`;const template_literal107=`\u1111`;const template_literal108=`\u{1111}`;const template_literal109=`\x10`;const template_literal110=`\\x10`;const template_literal111=`\\\\`;const template_literal112=``;const template_literal113=``;const template_literal113=`\x7f`;console.log(`\0`);console.log(`\x001`);console.log(`\0a`)
|
||||
`;const template_literal103=`\0z`;const template_literal104=`\0`;const template_literal105=`x``x`;const template_literal106=`😀`;const template_literal107=`\u1111`;const template_literal108=`\u{1111}`;const template_literal109=`\x10`;const template_literal110=`\\x10`;const template_literal111=`\\\\`;const template_literal112=``;const template_literal113=``;const template_literal114=`\x7f`;console.log(`\0`);console.log(`\x001`);console.log(`\0a`);const template_literal115=`\uD800`;const template_literal116=`\u{D800}`;const template_literal117=`\uDBFF`;const template_literal118=`\u{DBFF}`;const template_literal119=`\uDC00`;const template_literal120=`\u{DC00}`;const template_literal121=`\uDFFF`;const template_literal122=`\u{DFFF}`;const template_literal123=`\uFFFF`;const template_literal124=`\u{FFFF}`
|
||||
|
@ -77,12 +77,9 @@ pub enum SyntaxError {
|
||||
c: char,
|
||||
},
|
||||
InvalidStrEscape,
|
||||
InvalidUnicodeCodePoint,
|
||||
InvalidUnicodeEscape,
|
||||
InvalidCodePoint,
|
||||
ExpectedHexChars {
|
||||
/// Number of expected characters.
|
||||
count: u8,
|
||||
BadCharacterEscapeSequence {
|
||||
expected: &'static str,
|
||||
},
|
||||
NumLitTerminatedWithExp,
|
||||
LegacyCommentInModule,
|
||||
@ -294,11 +291,9 @@ impl SyntaxError {
|
||||
SyntaxError::IdentAfterNum => "Identifier cannot follow number".into(),
|
||||
SyntaxError::UnexpectedChar { c } => format!("Unexpected character {:?}", c).into(),
|
||||
SyntaxError::InvalidStrEscape => "Invalid string escape".into(),
|
||||
SyntaxError::InvalidUnicodeCodePoint => "Undefined Unicode code-point".into(),
|
||||
SyntaxError::InvalidUnicodeEscape => "Invalid unicode escape".into(),
|
||||
SyntaxError::InvalidCodePoint => "Invalid unicode code point".into(),
|
||||
SyntaxError::ExpectedHexChars { count } => {
|
||||
format!("Expected {} hex characters", count).into()
|
||||
SyntaxError::BadCharacterEscapeSequence { expected } => {
|
||||
format!("Bad character escape sequence, expected {}", expected).into()
|
||||
}
|
||||
SyntaxError::LegacyCommentInModule => {
|
||||
"Legacy comments cannot be used in module code".into()
|
||||
|
@ -480,7 +480,11 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
/// Read an escaped character for string literal.
|
||||
///
|
||||
/// In template literal, we should preserve raw string.
|
||||
fn read_escaped_char(&mut self, raw: &mut Raw, in_template: bool) -> LexResult<Option<Char>> {
|
||||
fn read_escaped_char(
|
||||
&mut self,
|
||||
raw: &mut Raw,
|
||||
in_template: bool,
|
||||
) -> LexResult<Option<Vec<Char>>> {
|
||||
debug_assert_eq!(self.cur(), Some('\\'));
|
||||
|
||||
let start = self.cur_pos();
|
||||
@ -509,11 +513,13 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
'f' => push_c_and_ret!('\u{000c}'),
|
||||
'\r' => {
|
||||
raw.push_str("\r");
|
||||
|
||||
self.bump(); // remove '\r'
|
||||
|
||||
if self.eat(b'\n') {
|
||||
raw.push_str("\n");
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
'\n' | '\u{2028}' | '\u{2029}' => {
|
||||
@ -524,20 +530,33 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
self.bump();
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// read hexadecimal escape sequences
|
||||
'x' => {
|
||||
raw.push_str("x");
|
||||
|
||||
self.bump(); // 'x'
|
||||
return self.read_hex_char(start, 2, raw).map(Some);
|
||||
|
||||
match self.read_int_u32::<16>(2, raw)? {
|
||||
Some(val) => return Ok(Some(vec![Char::from(val)])),
|
||||
None => self.error(
|
||||
start,
|
||||
SyntaxError::BadCharacterEscapeSequence {
|
||||
expected: "2 hex characters",
|
||||
},
|
||||
)?,
|
||||
}
|
||||
}
|
||||
|
||||
// read unicode escape sequences
|
||||
'u' => {
|
||||
return self.read_unicode_escape(start, raw).map(Some);
|
||||
}
|
||||
'u' => match self.read_unicode_escape(raw) {
|
||||
Ok(chars) => return Ok(Some(chars)),
|
||||
Err(err) => self.error(start, err.error.1)?,
|
||||
},
|
||||
|
||||
// octal escape sequences
|
||||
'0'..='7' => {
|
||||
raw.push(c);
|
||||
@ -548,7 +567,7 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
match self.cur() {
|
||||
Some(next) if next.is_digit(8) => c,
|
||||
// \0 is not an octal literal nor decimal literal.
|
||||
_ => return Ok(Some('\u{0000}'.into())),
|
||||
_ => return Ok(Some(vec!['\u{0000}'.into()])),
|
||||
}
|
||||
} else {
|
||||
c
|
||||
@ -575,31 +594,34 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
.and_then(|value| value.checked_add(v as u8));
|
||||
match new_val {
|
||||
Some(val) => val,
|
||||
None => return Ok(Some(value as char).map(From::from)),
|
||||
None => return Ok(Some(vec![Char::from(value as char)])),
|
||||
}
|
||||
} else {
|
||||
value * 8 + v as u8
|
||||
};
|
||||
|
||||
self.bump();
|
||||
raw.push(cur.unwrap());
|
||||
}
|
||||
_ => return Ok(Some(value as u32).map(From::from)),
|
||||
_ => return Ok(Some(vec![Char::from(value as u32)])),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
one!(false);
|
||||
one!(true);
|
||||
|
||||
return Ok(Some(value as char).map(From::from));
|
||||
return Ok(Some(vec![Char::from(value as char)]));
|
||||
}
|
||||
_ => {
|
||||
raw.push(c);
|
||||
c
|
||||
}
|
||||
};
|
||||
|
||||
self.input.bump();
|
||||
|
||||
Ok(Some(c.into()))
|
||||
Ok(Some(vec![c.into()]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -774,23 +796,31 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
// unicode escape
|
||||
'\\' => {
|
||||
l.bump();
|
||||
|
||||
if !l.is(b'u') {
|
||||
l.error_span(pos_span(start), SyntaxError::ExpectedUnicodeEscape)?
|
||||
}
|
||||
|
||||
has_escape = true;
|
||||
let c = l.read_unicode_escape(start, &mut Raw(None))?;
|
||||
let valid = if first {
|
||||
c.is_ident_start()
|
||||
} else {
|
||||
c.is_ident_part()
|
||||
};
|
||||
|
||||
if !valid {
|
||||
l.emit_error(start, SyntaxError::InvalidIdentChar);
|
||||
let chars = l.read_unicode_escape(&mut Raw(None))?;
|
||||
|
||||
if let Some(c) = chars.get(0) {
|
||||
let valid = if first {
|
||||
c.is_ident_start()
|
||||
} else {
|
||||
c.is_ident_part()
|
||||
};
|
||||
|
||||
if !valid {
|
||||
l.emit_error(start, SyntaxError::InvalidIdentChar);
|
||||
}
|
||||
}
|
||||
buf.extend(c);
|
||||
}
|
||||
|
||||
for c in chars {
|
||||
buf.extend(c);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
@ -803,53 +833,107 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
})
|
||||
}
|
||||
|
||||
fn read_unicode_escape(&mut self, start: BytePos, raw: &mut Raw) -> LexResult<Char> {
|
||||
fn read_unicode_escape(&mut self, raw: &mut Raw) -> LexResult<Vec<Char>> {
|
||||
debug_assert_eq!(self.cur(), Some('u'));
|
||||
self.bump();
|
||||
|
||||
let mut chars = vec![];
|
||||
let mut is_curly = false;
|
||||
|
||||
self.bump(); // 'u'
|
||||
|
||||
raw.push_str("u");
|
||||
|
||||
if self.eat(b'{') {
|
||||
is_curly = true;
|
||||
|
||||
raw.push('{');
|
||||
// let cp_start = self.cur_pos();
|
||||
let c = self.read_code_point(raw)?;
|
||||
}
|
||||
|
||||
if !self.eat(b'}') {
|
||||
self.error(start, SyntaxError::InvalidUnicodeEscape)?
|
||||
let state = self.input.cur_pos();
|
||||
let c = match self.read_int_u32::<16>(if is_curly { 0 } else { 4 }, raw) {
|
||||
Ok(Some(val)) => {
|
||||
if 0x0010_ffff >= val {
|
||||
char::from_u32(val)
|
||||
} else {
|
||||
let start = self.cur_pos();
|
||||
|
||||
self.error(
|
||||
start,
|
||||
SyntaxError::BadCharacterEscapeSequence {
|
||||
expected: if is_curly {
|
||||
"1-6 hex characters in the range 0 to 10FFFF."
|
||||
} else {
|
||||
"4 hex characters"
|
||||
},
|
||||
},
|
||||
)?
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let start = self.cur_pos();
|
||||
|
||||
self.error(
|
||||
start,
|
||||
SyntaxError::BadCharacterEscapeSequence {
|
||||
expected: if is_curly {
|
||||
"1-6 hex characters"
|
||||
} else {
|
||||
"4 hex characters"
|
||||
},
|
||||
},
|
||||
)?
|
||||
}
|
||||
};
|
||||
|
||||
match c {
|
||||
Some(c) => {
|
||||
chars.push(c.into());
|
||||
}
|
||||
_ => {
|
||||
self.input.reset_to(state);
|
||||
|
||||
chars.push(Char::from('\\'));
|
||||
chars.push(Char::from('u'));
|
||||
|
||||
if is_curly {
|
||||
chars.push(Char::from('{'));
|
||||
|
||||
for _ in 0..6 {
|
||||
if let Some(c) = self.input.cur() {
|
||||
if c == '}' {
|
||||
break;
|
||||
}
|
||||
|
||||
self.bump();
|
||||
|
||||
chars.push(Char::from(c));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
chars.push(Char::from('}'));
|
||||
} else {
|
||||
for _ in 0..4 {
|
||||
if let Some(c) = self.input.cur() {
|
||||
self.bump();
|
||||
|
||||
chars.push(Char::from(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_curly {
|
||||
if !self.eat(b'}') {
|
||||
self.error(state, SyntaxError::InvalidUnicodeEscape)?
|
||||
}
|
||||
|
||||
raw.push('}');
|
||||
|
||||
Ok(c)
|
||||
} else {
|
||||
self.read_hex_char(start, 4, raw)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// This method returns [Char] as non-utf8 character is valid in JavaScript.
|
||||
/// See https://github.com/swc-project/swc/issues/261
|
||||
fn read_hex_char(&mut self, start: BytePos, count: u8, raw: &mut Raw) -> LexResult<Char> {
|
||||
debug_assert!(count == 2 || count == 4);
|
||||
|
||||
// let pos = self.cur_pos();
|
||||
match self.read_int_u32::<16>(count, raw)? {
|
||||
Some(val) => Ok(val.into()),
|
||||
None => self.error(start, SyntaxError::ExpectedHexChars { count })?,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read `CodePoint`.
|
||||
fn read_code_point(&mut self, raw: &mut Raw) -> LexResult<Char> {
|
||||
let start = self.cur_pos();
|
||||
let val = self.read_int_u32::<16>(0, raw)?;
|
||||
match val {
|
||||
Some(val) if 0x0010_ffff >= val => match char::from_u32(val) {
|
||||
Some(c) => Ok(c.into()),
|
||||
None => self.error(start, SyntaxError::InvalidCodePoint)?,
|
||||
},
|
||||
_ => self.error(start, SyntaxError::InvalidCodePoint)?,
|
||||
}
|
||||
Ok(chars)
|
||||
}
|
||||
|
||||
/// See https://tc39.github.io/ecma262/#sec-literals-string-literals
|
||||
@ -862,6 +946,7 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
raw.push(quote);
|
||||
|
||||
self.bump(); // '"'
|
||||
|
||||
self.with_buf(|l, out| {
|
||||
while let Some(c) = {
|
||||
// Optimization
|
||||
@ -890,8 +975,10 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
|
||||
let mut wrapped = Raw(Some(String::new()));
|
||||
|
||||
if let Some(s) = l.read_escaped_char(&mut wrapped, false)? {
|
||||
out.extend(s);
|
||||
if let Some(chars) = l.read_escaped_char(&mut wrapped, false)? {
|
||||
for c in chars {
|
||||
out.extend(c);
|
||||
}
|
||||
}
|
||||
|
||||
raw.push_str(&wrapped.0.unwrap());
|
||||
@ -1019,9 +1106,11 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
let mut wrapped = Raw(Some(raw));
|
||||
|
||||
match self.read_escaped_char(&mut wrapped, true) {
|
||||
Ok(Some(s)) => {
|
||||
Ok(Some(chars)) => {
|
||||
if let Ok(ref mut cooked) = cooked {
|
||||
cooked.extend(s);
|
||||
for c in chars {
|
||||
cooked.extend(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
|
@ -268,9 +268,11 @@ fn tpl_invalid_unicode_escape() {
|
||||
Span {
|
||||
lo: BytePos(1),
|
||||
hi: BytePos(3),
|
||||
ctxt: SyntaxContext::empty()
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
SyntaxError::ExpectedHexChars { count: 4 }
|
||||
SyntaxError::BadCharacterEscapeSequence {
|
||||
expected: "4 hex characters"
|
||||
}
|
||||
))
|
||||
}),
|
||||
raw: "\\unicode".into(),
|
||||
@ -286,11 +288,13 @@ fn tpl_invalid_unicode_escape() {
|
||||
cooked: Err(Error {
|
||||
error: Box::new((
|
||||
Span {
|
||||
lo: BytePos(4),
|
||||
lo: BytePos(1),
|
||||
hi: BytePos(4),
|
||||
ctxt: SyntaxContext::empty()
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
SyntaxError::InvalidCodePoint
|
||||
SyntaxError::BadCharacterEscapeSequence {
|
||||
expected: "1-6 hex characters"
|
||||
}
|
||||
))
|
||||
}),
|
||||
raw: "\\u{".into(),
|
||||
@ -308,9 +312,11 @@ fn tpl_invalid_unicode_escape() {
|
||||
Span {
|
||||
lo: BytePos(1),
|
||||
hi: BytePos(3),
|
||||
ctxt: SyntaxContext::empty()
|
||||
ctxt: SyntaxContext::empty(),
|
||||
},
|
||||
SyntaxError::ExpectedHexChars { count: 2 }
|
||||
SyntaxError::BadCharacterEscapeSequence {
|
||||
expected: "2 hex characters"
|
||||
}
|
||||
))
|
||||
}),
|
||||
raw: "\\xhex".into(),
|
||||
|
1
crates/swc_ecma_parser/tests/jsx/basic/22/input.js
Normal file
1
crates/swc_ecma_parser/tests/jsx/basic/22/input.js
Normal file
@ -0,0 +1 @@
|
||||
<div>this should not parse as unicode: \u00a0</div>;
|
78
crates/swc_ecma_parser/tests/jsx/basic/22/input.js.json
Normal file
78
crates/swc_ecma_parser/tests/jsx/basic/22/input.js.json
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 52,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 52,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "JSXElement",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 51,
|
||||
"ctxt": 0
|
||||
},
|
||||
"opening": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 1,
|
||||
"end": 4,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
},
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 5,
|
||||
"ctxt": 0
|
||||
},
|
||||
"attributes": [],
|
||||
"selfClosing": false,
|
||||
"typeArguments": null
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "JSXText",
|
||||
"span": {
|
||||
"start": 5,
|
||||
"end": 45,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "this should not parse as unicode: \\u00a0",
|
||||
"raw": "this should not parse as unicode: \\u00a0"
|
||||
}
|
||||
],
|
||||
"closing": {
|
||||
"type": "JSXClosingElement",
|
||||
"span": {
|
||||
"start": 45,
|
||||
"end": 51,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 47,
|
||||
"end": 50,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
3
crates/swc_ecma_parser/tests/jsx/basic/string/input.js
Normal file
3
crates/swc_ecma_parser/tests/jsx/basic/string/input.js
Normal file
@ -0,0 +1,3 @@
|
||||
const x = <div onclick={{ s: "\uD800" }}></div>;
|
||||
const x = <div onclick={{ s: "\u{D800}" }}></div>;
|
||||
|
291
crates/swc_ecma_parser/tests/jsx/basic/string/input.js.json
Normal file
291
crates/swc_ecma_parser/tests/jsx/basic/string/input.js.json
Normal file
@ -0,0 +1,291 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 99,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 48,
|
||||
"ctxt": 0
|
||||
},
|
||||
"kind": "const",
|
||||
"declare": false,
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 47,
|
||||
"ctxt": 0
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 7,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "x",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
},
|
||||
"init": {
|
||||
"type": "JSXElement",
|
||||
"span": {
|
||||
"start": 10,
|
||||
"end": 47,
|
||||
"ctxt": 0
|
||||
},
|
||||
"opening": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 11,
|
||||
"end": 14,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
},
|
||||
"span": {
|
||||
"start": 10,
|
||||
"end": 41,
|
||||
"ctxt": 0
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"span": {
|
||||
"start": 15,
|
||||
"end": 40,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 15,
|
||||
"end": 22,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "onclick",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"span": {
|
||||
"start": 23,
|
||||
"end": 40,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 24,
|
||||
"end": 39,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "KeyValueProperty",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 26,
|
||||
"end": 27,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "s",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "StringLiteral",
|
||||
"span": {
|
||||
"start": 29,
|
||||
"end": 37,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "\\uD800",
|
||||
"raw": "\"\\uD800\""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"typeArguments": null
|
||||
},
|
||||
"children": [],
|
||||
"closing": {
|
||||
"type": "JSXClosingElement",
|
||||
"span": {
|
||||
"start": 41,
|
||||
"end": 47,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 43,
|
||||
"end": 46,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"definite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"span": {
|
||||
"start": 49,
|
||||
"end": 99,
|
||||
"ctxt": 0
|
||||
},
|
||||
"kind": "const",
|
||||
"declare": false,
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"span": {
|
||||
"start": 55,
|
||||
"end": 98,
|
||||
"ctxt": 0
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 55,
|
||||
"end": 56,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "x",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
},
|
||||
"init": {
|
||||
"type": "JSXElement",
|
||||
"span": {
|
||||
"start": 59,
|
||||
"end": 98,
|
||||
"ctxt": 0
|
||||
},
|
||||
"opening": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 60,
|
||||
"end": 63,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
},
|
||||
"span": {
|
||||
"start": 59,
|
||||
"end": 92,
|
||||
"ctxt": 0
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"span": {
|
||||
"start": 64,
|
||||
"end": 91,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 64,
|
||||
"end": 71,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "onclick",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"span": {
|
||||
"start": 72,
|
||||
"end": 91,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 73,
|
||||
"end": 90,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "KeyValueProperty",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 75,
|
||||
"end": 76,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "s",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "StringLiteral",
|
||||
"span": {
|
||||
"start": 78,
|
||||
"end": 88,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "\\u{D800}",
|
||||
"raw": "\"\\u{D800}\""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"typeArguments": null
|
||||
},
|
||||
"children": [],
|
||||
"closing": {
|
||||
"type": "JSXClosingElement",
|
||||
"span": {
|
||||
"start": 92,
|
||||
"end": 98,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 94,
|
||||
"end": 97,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"definite": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
3
crates/swc_ecma_parser/tests/jsx/basic/template/input.js
Normal file
3
crates/swc_ecma_parser/tests/jsx/basic/template/input.js
Normal file
@ -0,0 +1,3 @@
|
||||
const x = <div onclick={{ t: `\uD800` }}></div>;
|
||||
const x = <div onclick={{ t: `\u{D800}` }}></div>;
|
||||
|
315
crates/swc_ecma_parser/tests/jsx/basic/template/input.js.json
Normal file
315
crates/swc_ecma_parser/tests/jsx/basic/template/input.js.json
Normal file
@ -0,0 +1,315 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 99,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 48,
|
||||
"ctxt": 0
|
||||
},
|
||||
"kind": "const",
|
||||
"declare": false,
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 47,
|
||||
"ctxt": 0
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 6,
|
||||
"end": 7,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "x",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
},
|
||||
"init": {
|
||||
"type": "JSXElement",
|
||||
"span": {
|
||||
"start": 10,
|
||||
"end": 47,
|
||||
"ctxt": 0
|
||||
},
|
||||
"opening": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 11,
|
||||
"end": 14,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
},
|
||||
"span": {
|
||||
"start": 10,
|
||||
"end": 41,
|
||||
"ctxt": 0
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"span": {
|
||||
"start": 15,
|
||||
"end": 40,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 15,
|
||||
"end": 22,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "onclick",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"span": {
|
||||
"start": 23,
|
||||
"end": 40,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 24,
|
||||
"end": 39,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "KeyValueProperty",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 26,
|
||||
"end": 27,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "t",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "TemplateLiteral",
|
||||
"span": {
|
||||
"start": 29,
|
||||
"end": 37,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expressions": [],
|
||||
"quasis": [
|
||||
{
|
||||
"type": "TemplateElement",
|
||||
"span": {
|
||||
"start": 30,
|
||||
"end": 36,
|
||||
"ctxt": 0
|
||||
},
|
||||
"tail": true,
|
||||
"cooked": "\\uD800",
|
||||
"raw": "\\uD800"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"typeArguments": null
|
||||
},
|
||||
"children": [],
|
||||
"closing": {
|
||||
"type": "JSXClosingElement",
|
||||
"span": {
|
||||
"start": 41,
|
||||
"end": 47,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 43,
|
||||
"end": 46,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"definite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"span": {
|
||||
"start": 49,
|
||||
"end": 99,
|
||||
"ctxt": 0
|
||||
},
|
||||
"kind": "const",
|
||||
"declare": false,
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"span": {
|
||||
"start": 55,
|
||||
"end": 98,
|
||||
"ctxt": 0
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 55,
|
||||
"end": 56,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "x",
|
||||
"optional": false,
|
||||
"typeAnnotation": null
|
||||
},
|
||||
"init": {
|
||||
"type": "JSXElement",
|
||||
"span": {
|
||||
"start": 59,
|
||||
"end": 98,
|
||||
"ctxt": 0
|
||||
},
|
||||
"opening": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 60,
|
||||
"end": 63,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
},
|
||||
"span": {
|
||||
"start": 59,
|
||||
"end": 92,
|
||||
"ctxt": 0
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"span": {
|
||||
"start": 64,
|
||||
"end": 91,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 64,
|
||||
"end": 71,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "onclick",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"span": {
|
||||
"start": 72,
|
||||
"end": 91,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"span": {
|
||||
"start": 73,
|
||||
"end": 90,
|
||||
"ctxt": 0
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "KeyValueProperty",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 75,
|
||||
"end": 76,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "t",
|
||||
"optional": false
|
||||
},
|
||||
"value": {
|
||||
"type": "TemplateLiteral",
|
||||
"span": {
|
||||
"start": 78,
|
||||
"end": 88,
|
||||
"ctxt": 0
|
||||
},
|
||||
"expressions": [],
|
||||
"quasis": [
|
||||
{
|
||||
"type": "TemplateElement",
|
||||
"span": {
|
||||
"start": 79,
|
||||
"end": 87,
|
||||
"ctxt": 0
|
||||
},
|
||||
"tail": true,
|
||||
"cooked": "\\u{D800}",
|
||||
"raw": "\\u{D800}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"typeArguments": null
|
||||
},
|
||||
"children": [],
|
||||
"closing": {
|
||||
"type": "JSXClosingElement",
|
||||
"span": {
|
||||
"start": 92,
|
||||
"end": 98,
|
||||
"ctxt": 0
|
||||
},
|
||||
"name": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 94,
|
||||
"end": 97,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "div",
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"definite": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -0,0 +1 @@
|
||||
const string = "\xZZ";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence/input.js:1:1]
|
||||
1 | const string = "\xZZ";
|
||||
: ^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\x";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence_1/input.js:1:1]
|
||||
1 | const string = "\x";
|
||||
: ^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\uZZZZ";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence_2/input.js:1:1]
|
||||
1 | const string = "\uZZZZ";
|
||||
: ^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\u{FFFFFF}";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 1-6 hex characters in the range 0 to 10FFFF.
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence_3/input.js:1:1]
|
||||
1 | const string = "\u{FFFFFF}";
|
||||
: ^^^^^^^^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\xFZ";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence_4/input.js:1:1]
|
||||
1 | const string = "\xFZ";
|
||||
: ^^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\u{ZZZZ}";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 1-6 hex characters
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence_5/input.js:1:1]
|
||||
1 | const string = "\u{ZZZZ}";
|
||||
: ^^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\u{FFFFFF}";
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Bad character escape sequence, expected 1-6 hex characters in the range 0 to 10FFFF.
|
||||
,-[$DIR/tests/pat/errors/bad_character_escape_sequence_6/input.js:1:1]
|
||||
1 | const string = "\u{FFFFFF}";
|
||||
: ^^^^^^^^^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Invalid string escape
|
||||
,-[$DIR/tests/pat/errors/unterminated_string_constant/input.js:1:1]
|
||||
1 | const string = "\
|
||||
: ^
|
||||
`----
|
@ -0,0 +1 @@
|
||||
const string = "\"
|
@ -0,0 +1,6 @@
|
||||
|
||||
x Unterminated string constant
|
||||
,-[$DIR/tests/pat/errors/unterminated_string_constant_1/input.js:1:1]
|
||||
1 | const string = "\"
|
||||
: ^^^
|
||||
`----
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/0c7d4912f3869297.js:1:1]
|
||||
1 | \u12
|
||||
: ^^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/0f2794d0bcec2dd7.js:1:1]
|
||||
1 | '\x1
|
||||
: ^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Invalid unicode code point
|
||||
x Bad character escape sequence, expected 1-6 hex characters in the range 0 to 10FFFF.
|
||||
,-[$DIR/tests/test262-parser/fail/14eaa7e71c682461.js:1:1]
|
||||
1 | ("\u{FFFFFFF}")
|
||||
: ^^^^^^^
|
||||
: ^^^^^^^^^^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/26031afc9eaef976.js:1:1]
|
||||
1 | a\u11z
|
||||
: ^^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Invalid unicode code point
|
||||
x Bad character escape sequence, expected 1-6 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/2687d6d9043bd5cb.js:1:1]
|
||||
1 | "\u{}"
|
||||
: ^
|
||||
: ^^^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/28151222a45ac800.js:1:1]
|
||||
1 | \ua
|
||||
: ^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/3b473034dde14c98.js:1:1]
|
||||
1 | "\xx";
|
||||
: ^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/55b9f51ad21c7f25.js:1:1]
|
||||
1 | "\u";
|
||||
: ^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/575367951ac8635d.js:1:1]
|
||||
1 | ('\u')
|
||||
: ^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/5a627d08e9b33ad1.js:1:1]
|
||||
1 | "\u00";
|
||||
: ^^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/610fe4450d41c81e.js:1:1]
|
||||
1 | \u
|
||||
: ^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/61b72f954b679c22.js:1:1]
|
||||
1 | \u1
|
||||
: ^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/66dd7a60a05be9f8.js:1:1]
|
||||
1 | '\x1
|
||||
: ^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/6a96389a0cce57e9.js:1:1]
|
||||
1 | var x = /[a-z]/\ux
|
||||
: ^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/6c3a76d368c398cc.js:1:1]
|
||||
1 | a\u1z
|
||||
: ^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/6cb3fc8ff354bd89.js:1:1]
|
||||
1 | a\uz
|
||||
: ^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/73b0a0c9a26e1950.js:1:1]
|
||||
1 | a\u113
|
||||
: ^^^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/73c84046ac613107.js:1:1]
|
||||
1 | "\ux";
|
||||
: ^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/783f01472f94a412.js:1:1]
|
||||
1 | "\u000";
|
||||
: ^^^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/92dfbd6c58d2c61f.js:1:1]
|
||||
1 | a\u
|
||||
: ^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/92ed8c5d2d151ff9.js:1:1]
|
||||
1 | '\x
|
||||
: ^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/94535dc25ef762ee.js:1:1]
|
||||
1 | var x = /[a-z]/\\ux
|
||||
: ^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Invalid unicode code point
|
||||
x Bad character escape sequence, expected 1-6 hex characters in the range 0 to 10FFFF.
|
||||
,-[$DIR/tests/test262-parser/fail/aca911e336954a5b.js:1:1]
|
||||
1 | ("\u{110000}")
|
||||
: ^^^^^^
|
||||
: ^^^^^^^^^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/b3fc8ced7ce28c35.js:1:1]
|
||||
1 | ('\x')
|
||||
: ^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/b61406dafcaab4b7.js:1:1]
|
||||
1 | ('\x0')
|
||||
: ^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/bdb40451ba403567.js:1:1]
|
||||
1 | a\u1
|
||||
: ^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,8 +1,8 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/c3afed3cb0fb92ab.js:1:1]
|
||||
1 | \uD800\u
|
||||
: ^^
|
||||
: ^
|
||||
`----
|
||||
|
||||
x Invalid character in identifier
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/c79647e7baf81f8f.js:1:1]
|
||||
1 | "\x0";
|
||||
: ^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/c86a72939cce6f53.js:1:1]
|
||||
1 | "\u
|
||||
: ^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/f03be7c48423eaed.js:1:1]
|
||||
1 | \u113
|
||||
: ^^^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/f6dc8a19882274b5.js:1:1]
|
||||
1 | a\u12
|
||||
: ^^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Invalid unicode code point
|
||||
x Bad character escape sequence, expected 1-6 hex characters in the range 0 to 10FFFF.
|
||||
,-[$DIR/tests/test262-parser/fail/f8b20220d8c85d71.js:1:1]
|
||||
1 | "\u{110000}"
|
||||
: ^^^^^^
|
||||
: ^^^^^^^^^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/fc8bfabd18ec26dc.js:1:1]
|
||||
1 | "\u0";
|
||||
: ^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
x Expected 4 hex characters
|
||||
x Bad character escape sequence, expected 4 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/fefae4f97aa879de.js:1:1]
|
||||
1 | a\u111z
|
||||
: ^^^^^
|
||||
: ^
|
||||
`----
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
x Expected 2 hex characters
|
||||
x Bad character escape sequence, expected 2 hex characters
|
||||
,-[$DIR/tests/test262-parser/fail/ffcb5a1d89aed63f.js:1:1]
|
||||
1 | "\x";
|
||||
: ^^
|
||||
|
@ -1438,21 +1438,21 @@ where
|
||||
}
|
||||
|
||||
fn nth_char(s: &str, mut idx: usize) -> Cow<str> {
|
||||
if !s.contains("\\\0") {
|
||||
if !s.contains("\\ud") && !s.contains("\\uD") {
|
||||
return Cow::Owned(s.chars().nth(idx).unwrap().to_string());
|
||||
}
|
||||
|
||||
let mut iter = s.chars().peekable();
|
||||
|
||||
while let Some(c) = iter.next() {
|
||||
if c == '\\' && iter.peek().copied() == Some('\0') {
|
||||
if c == '\\' && iter.peek().copied() == Some('u') {
|
||||
if idx == 0 {
|
||||
let mut buf = String::new();
|
||||
buf.push('\\');
|
||||
buf.extend(iter.take(6));
|
||||
buf.extend(iter.take(5));
|
||||
return Cow::Owned(buf);
|
||||
} else {
|
||||
for _ in 0..6 {
|
||||
for _ in 0..5 {
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
|
@ -972,8 +972,8 @@ fn test_fold_get_elem2_1() {
|
||||
fold("x = 'string'[5]", "x = \"g\"");
|
||||
fold("x = 'string'[0]", "x = \"s\"");
|
||||
fold("x = 's'[0]", "x = \"s\"");
|
||||
fold("x = '\\uD83D\\uDCA9'[0]", "x = \"\\ud83d\"");
|
||||
fold("x = '\\uD83D\\uDCA9'[1]", "x = \"\\udca9\"");
|
||||
fold("x = '\\uD83D\\uDCA9'[0]", "x = \"\\uD83D\"");
|
||||
fold("x = '\\uD83D\\uDCA9'[1]", "x = \"\\uDCA9\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user