1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198 |
- package parser
- import (
- "errors"
- "regexp"
- "strings"
- "testing"
- "github.com/dop251/goja/ast"
- "github.com/dop251/goja/file"
- "github.com/dop251/goja/token"
- "github.com/dop251/goja/unistring"
- )
- func firstErr(err error) error {
- switch err := err.(type) {
- case ErrorList:
- return err[0]
- }
- return err
- }
- var matchBeforeAfterSeparator = regexp.MustCompile(`(?m)^[ \t]*---$`)
- func testParse(src string) (parser *_parser, program *ast.Program, err error) {
- defer func() {
- if tmp := recover(); tmp != nil {
- switch tmp := tmp.(type) {
- case string:
- if strings.HasPrefix(tmp, "SyntaxError:") {
- parser = nil
- program = nil
- err = errors.New(tmp)
- return
- }
- }
- panic(tmp)
- }
- }()
- parser = newParser("", src)
- program, err = parser.parse()
- return
- }
- func TestParseFile(t *testing.T) {
- tt(t, func() {
- _, err := ParseFile(nil, "", `/abc/`, 0)
- is(err, nil)
- _, err = ParseFile(nil, "", `/(?!def)abc/`, IgnoreRegExpErrors)
- is(err, nil)
- _, err = ParseFile(nil, "", `/(?!def)abc/; return`, IgnoreRegExpErrors)
- is(err, "(anonymous): Line 1:15 Illegal return statement")
- })
- }
- func TestParseFunction(t *testing.T) {
- tt(t, func() {
- test := func(prm, bdy string, expect interface{}) *ast.FunctionLiteral {
- function, err := ParseFunction(prm, bdy)
- is(firstErr(err), expect)
- return function
- }
- test("a, b,c,d", "", nil)
- test("a, b;,c,d", "", "(anonymous): Line 1:15 Unexpected token ;")
- test("this", "", "(anonymous): Line 1:11 Unexpected token this")
- test("a, b, c, null", "", "(anonymous): Line 1:20 Unexpected token null")
- test("a, b,c,d", "return;", nil)
- test("a, b,c,d", "break;", "(anonymous): Line 2:1 Illegal break statement")
- test("a, b,c,d", "{}", nil)
- })
- }
- func TestParserErr(t *testing.T) {
- tt(t, func() {
- test := func(input string, expect interface{}) (*ast.Program, *_parser) {
- parser := newParser("", input)
- program, err := parser.parse()
- is(firstErr(err), expect)
- return program, parser
- }
- test("", nil)
- program, parser := test(`
- var abc;
- break; do {
- } while(true);
- `, "(anonymous): Line 3:9 Illegal break statement")
- {
- stmt := program.Body[1].(*ast.BadStatement)
- is(parser.position(stmt.From).Column, 9)
- is(parser.position(stmt.To).Column, 16)
- is(parser.slice(stmt.From, stmt.To), "break; ")
- }
- s := string([]byte{0x22, 0x25, 0x21, 0x63, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x25, 0x63, 0x25, 0x9c, 0x29, 0x25, 0x21, 0x5c, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x5c, 0xe2, 0x80, 0xa9, 0x29, 0x78, 0x39, 0x63, 0x22})
- test(s, `(anonymous): Line 1:16 Invalid UTF-8 character`)
- test("{", "(anonymous): Line 1:2 Unexpected end of input")
- test("}", "(anonymous): Line 1:1 Unexpected token }")
- test("3ea", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3in", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3in []", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3e", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3e+", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3e-", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3x", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("3x0", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("0x", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("09", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("018", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("01.0", "(anonymous): Line 1:3 Unexpected number")
- test(".0.9", "(anonymous): Line 1:3 Unexpected number")
- test("0o3e1", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("01a", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("0x3in[]", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\"Hello\nWorld\"", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\u203f = 10", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("x\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("x\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("x\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("x\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("x\\\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("/\n", "(anonymous): Line 1:1 Invalid regular expression: missing /")
- test("0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment")
- test("func() = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment")
- test("(1 + 1) = 2", "(anonymous): Line 1:2 Invalid left-hand side in assignment")
- test("1++", "(anonymous): Line 1:2 Invalid left-hand side in assignment")
- test("1--", "(anonymous): Line 1:2 Invalid left-hand side in assignment")
- test("--1", "(anonymous): Line 1:1 Invalid left-hand side in assignment")
- test("for((1 + 1) in abc) def();", "(anonymous): Line 1:1 Invalid left-hand side in for-in or for-of")
- test("[", "(anonymous): Line 1:2 Unexpected end of input")
- test("[,", "(anonymous): Line 1:3 Unexpected end of input")
- test("1 + {", "(anonymous): Line 1:6 Unexpected end of input")
- test("1 + { abc:abc", "(anonymous): Line 1:14 Unexpected end of input")
- test("1 + { abc:abc,", "(anonymous): Line 1:15 Unexpected end of input")
- test("var abc = /\n/", "(anonymous): Line 1:11 Invalid regular expression: missing /")
- test("var abc = \"\n", "(anonymous): Line 1:11 Unexpected token ILLEGAL")
- test("var if = 0", "(anonymous): Line 1:5 Unexpected token if")
- test("abc + 0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment")
- test("+abc = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment")
- test("1 + (", "(anonymous): Line 1:6 Unexpected end of input")
- test("\n\n\n{", "(anonymous): Line 4:2 Unexpected end of input")
- test("\n/* Some multiline\ncomment */\n)", "(anonymous): Line 4:1 Unexpected token )")
- // TODO
- //{ set 1 }
- //{ get 2 }
- //({ set: s(if) { } })
- //({ set s(.) { } })
- //({ set: s() { } })
- //({ set: s(a, b) { } })
- //({ get: g(d) { } })
- //({ get i() { }, i: 42 })
- //({ i: 42, get i() { } })
- //({ set i(x) { }, i: 42 })
- //({ i: 42, set i(x) { } })
- //({ get i() { }, get i() { } })
- //({ set i(x) { }, set i(x) { } })
- test("function abc(if) {}", "(anonymous): Line 1:14 Unexpected token if")
- test("function abc(true) {}", "(anonymous): Line 1:14 Unexpected token true")
- test("function abc(false) {}", "(anonymous): Line 1:14 Unexpected token false")
- test("function abc(null) {}", "(anonymous): Line 1:14 Unexpected token null")
- test("function null() {}", "(anonymous): Line 1:10 Unexpected token null")
- test("function true() {}", "(anonymous): Line 1:10 Unexpected token true")
- test("function false() {}", "(anonymous): Line 1:10 Unexpected token false")
- test("function if() {}", "(anonymous): Line 1:10 Unexpected token if")
- test("a b;", "(anonymous): Line 1:3 Unexpected identifier")
- test("if.a", "(anonymous): Line 1:3 Unexpected token .")
- test("a if", "(anonymous): Line 1:3 Unexpected token if")
- test("a class", "(anonymous): Line 1:3 Unexpected reserved word")
- test("break\n", "(anonymous): Line 1:1 Illegal break statement")
- test("break 1;", "(anonymous): Line 1:7 Unexpected number")
- test("for (;;) { break 1; }", "(anonymous): Line 1:18 Unexpected number")
- test("continue\n", "(anonymous): Line 1:1 Illegal continue statement")
- test("continue 1;", "(anonymous): Line 1:10 Unexpected number")
- test("for (;;) { continue 1; }", "(anonymous): Line 1:21 Unexpected number")
- test("throw", "(anonymous): Line 1:1 Unexpected end of input")
- test("throw;", "(anonymous): Line 1:6 Unexpected token ;")
- test("throw \n", "(anonymous): Line 1:1 Unexpected end of input")
- test("for (var abc, def in {});", "(anonymous): Line 1:19 Unexpected token in")
- test("for ((abc in {});;);", nil)
- test("for ((abc in {}));", "(anonymous): Line 1:17 Unexpected token )")
- test("for (+abc in {});", "(anonymous): Line 1:1 Invalid left-hand side in for-in or for-of")
- test("if (false)", "(anonymous): Line 1:11 Unexpected end of input")
- test("if (false) abc(); else", "(anonymous): Line 1:23 Unexpected end of input")
- test("do", "(anonymous): Line 1:3 Unexpected end of input")
- test("while (false)", "(anonymous): Line 1:14 Unexpected end of input")
- test("for (;;)", "(anonymous): Line 1:9 Unexpected end of input")
- test("with (abc)", "(anonymous): Line 1:11 Unexpected end of input")
- test("try {}", "(anonymous): Line 1:1 Missing catch or finally after try")
- test("try {} catch () {}", "(anonymous): Line 1:15 Unexpected token )")
- test("\u203f = 1", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- // TODO
- // const x = 12, y;
- // const x, y = 12;
- // const x;
- // if(true) let a = 1;
- // if(true) const a = 1;
- test(`new abc()."def"`, "(anonymous): Line 1:11 Unexpected string")
- test("/*", "(anonymous): Line 1:3 Unexpected end of input")
- test("/**", "(anonymous): Line 1:4 Unexpected end of input")
- test("/*\n\n\n", "(anonymous): Line 4:1 Unexpected end of input")
- test("/*\n\n\n*", "(anonymous): Line 4:2 Unexpected end of input")
- test("/*abc", "(anonymous): Line 1:6 Unexpected end of input")
- test("/*abc *", "(anonymous): Line 1:9 Unexpected end of input")
- test("\n]", "(anonymous): Line 2:1 Unexpected token ]")
- test("\r\n]", "(anonymous): Line 2:1 Unexpected token ]")
- test("\n\r]", "(anonymous): Line 3:1 Unexpected token ]")
- test("//\r\n]", "(anonymous): Line 2:1 Unexpected token ]")
- test("//\n\r]", "(anonymous): Line 3:1 Unexpected token ]")
- test("/abc\\\n/", "(anonymous): Line 1:1 Invalid regular expression: missing /")
- test("//\r \n]", "(anonymous): Line 3:1 Unexpected token ]")
- test("/*\r\n*/]", "(anonymous): Line 2:3 Unexpected token ]")
- test("/*\r \n*/]", "(anonymous): Line 3:3 Unexpected token ]")
- test("\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\\abc", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\\u0000", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\\u200c = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("\\u200D = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test(`"\`, "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test(`"\u`, "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("return", "(anonymous): Line 1:1 Illegal return statement")
- test("continue", "(anonymous): Line 1:1 Illegal continue statement")
- test("break", "(anonymous): Line 1:1 Illegal break statement")
- test("switch (abc) { default: continue; }", "(anonymous): Line 1:25 Illegal continue statement")
- test("do { abc } *", "(anonymous): Line 1:12 Unexpected token *")
- test("while (true) { break abc; }", "(anonymous): Line 1:16 Undefined label 'abc'")
- test("while (true) { continue abc; }", "(anonymous): Line 1:16 Undefined label 'abc'")
- test("abc: while (true) { (function(){ break abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'")
- test("abc: while (true) { (function(){ abc: break abc; }); }", nil)
- test("abc: while (true) { (function(){ continue abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'")
- test(`abc: if (0) break abc; else {}`, nil)
- test(`abc: if (0) { break abc; } else {}`, nil)
- test(`abc: if (0) { break abc } else {}`, nil)
- test("abc: while (true) { abc: while (true) {} }", "(anonymous): Line 1:21 Label 'abc' already exists")
- test(`if(0) { do { } while(0) } else { do { } while(0) }`, nil)
- test(`if(0) do { } while(0); else do { } while(0)`, nil)
- test("_: _: while (true) {]", "(anonymous): Line 1:4 Label '_' already exists")
- test("_:\n_:\nwhile (true) {]", "(anonymous): Line 2:1 Label '_' already exists")
- test("_:\n _:\nwhile (true) {]", "(anonymous): Line 2:4 Label '_' already exists")
- test("function(){}", "(anonymous): Line 1:9 Unexpected token (")
- test("\n/*/", "(anonymous): Line 2:4 Unexpected end of input")
- test("/*/.source", "(anonymous): Line 1:11 Unexpected end of input")
- test("var class", "(anonymous): Line 1:5 Unexpected reserved word")
- test("var if", "(anonymous): Line 1:5 Unexpected token if")
- test("object Object", "(anonymous): Line 1:8 Unexpected identifier")
- test("[object Object]", "(anonymous): Line 1:9 Unexpected identifier")
- test("\\u0xyz", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test(`for (var abc, def in {}) {}`, "(anonymous): Line 1:19 Unexpected token in")
- test(`for (abc, def in {}) {}`, "(anonymous): Line 1:1 Invalid left-hand side in for-in or for-of")
- test(`for (var abc=def, ghi=("abc" in {}); true;) {}`, nil)
- {
- // Semicolon insertion
- test("this\nif (1);", nil)
- test("while (1) { break\nif (1); }", nil)
- test("throw\nif (1);", "(anonymous): Line 1:1 Illegal newline after throw")
- test("(function(){ return\nif (1); })", nil)
- test("while (1) { continue\nif (1); }", nil)
- test("debugger\nif (1);", nil)
- }
- { // Reserved words
- test("class", "(anonymous): Line 1:1 Unexpected reserved word")
- test("abc.class = 1", nil)
- test("var class;", "(anonymous): Line 1:5 Unexpected reserved word")
- test("const", "(anonymous): Line 1:6 Unexpected end of input")
- test("abc.const = 1", nil)
- test("var const;", "(anonymous): Line 1:5 Unexpected token const")
- test("enum", "(anonymous): Line 1:1 Unexpected reserved word")
- test("abc.enum = 1", nil)
- test("var enum;", "(anonymous): Line 1:5 Unexpected reserved word")
- test("export", "(anonymous): Line 1:1 Unexpected reserved word")
- test("abc.export = 1", nil)
- test("var export;", "(anonymous): Line 1:5 Unexpected reserved word")
- test("extends", "(anonymous): Line 1:1 Unexpected reserved word")
- test("abc.extends = 1", nil)
- test("var extends;", "(anonymous): Line 1:5 Unexpected reserved word")
- test("import", "(anonymous): Line 1:1 Unexpected reserved word")
- test("abc.import = 1", nil)
- test("var import;", "(anonymous): Line 1:5 Unexpected reserved word")
- test("super", "(anonymous): Line 1:1 Unexpected reserved word")
- test("abc.super = 1", nil)
- test("var super;", "(anonymous): Line 1:5 Unexpected reserved word")
- test(`
- obj = {
- aaa: 1
- bbb: "string"
- };`, "(anonymous): Line 4:6 Unexpected identifier")
- test("{}", nil)
- test("{a: 1}", nil)
- test("{a: 1,}", "(anonymous): Line 1:7 Unexpected token }")
- test("{a: 1, b: 2}", "(anonymous): Line 1:9 Unexpected token :")
- test("{a: 1, b: 2,}", "(anonymous): Line 1:9 Unexpected token :")
- test(`let f = () => new import('');`, "(anonymous): Line 1:19 Unexpected reserved word")
- }
- { // Reserved words (strict)
- test(`implements`, nil)
- test(`abc.implements = 1`, nil)
- test(`var implements;`, nil)
- test(`interface`, nil)
- test(`abc.interface = 1`, nil)
- test(`var interface;`, nil)
- test(`let`, nil)
- test(`abc.let = 1`, nil)
- test(`var let;`, nil)
- test(`package`, nil)
- test(`abc.package = 1`, nil)
- test(`var package;`, nil)
- test(`private`, nil)
- test(`abc.private = 1`, nil)
- test(`var private;`, nil)
- test(`protected`, nil)
- test(`abc.protected = 1`, nil)
- test(`var protected;`, nil)
- test(`public`, nil)
- test(`abc.public = 1`, nil)
- test(`var public;`, nil)
- test(`static`, nil)
- test(`abc.static = 1`, nil)
- test(`var static;`, nil)
- test(`yield`, nil)
- test(`abc.yield = 1`, nil)
- test(`var yield;`, nil)
- }
- test(`0, { get a(param = null) {} };`, "(anonymous): Line 1:11 Getter must not have any formal parameters.")
- test(`let{f(`, "(anonymous): Line 1:7 Unexpected end of input")
- test("`", "(anonymous): Line 1:2 Unexpected end of input")
- test(" `", "(anonymous): Line 1:3 Unexpected end of input")
- test("` ", "(anonymous): Line 1:3 Unexpected end of input")
- })
- }
- func TestParser(t *testing.T) {
- tt(t, func() {
- test := func(source string, chk interface{}) *ast.Program {
- _, program, err := testParse(source)
- is(firstErr(err), chk)
- return program
- }
- test(`new (() => {});`, nil)
- test(`
- abc
- --
- []
- `, "(anonymous): Line 3:13 Invalid left-hand side in assignment")
- test(`
- abc--
- []
- `, nil)
- test("1\n[]\n", "(anonymous): Line 2:2 Unexpected token ]")
- test(`
- function abc() {
- }
- abc()
- `, nil)
- test("", nil)
- test("//", nil)
- test("/* */", nil)
- test("/** **/", nil)
- test("/*****/", nil)
- test("/*", "(anonymous): Line 1:3 Unexpected end of input")
- test("#", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("/**/#", "(anonymous): Line 1:5 Unexpected token ILLEGAL")
- test("new +", "(anonymous): Line 1:5 Unexpected token +")
- program := test(";", nil)
- is(len(program.Body), 1)
- is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1))
- program = test(";;", nil)
- is(len(program.Body), 2)
- is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1))
- is(program.Body[1].(*ast.EmptyStatement).Semicolon, file.Idx(2))
- program = test("1.2", nil)
- is(len(program.Body), 1)
- is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2")
- program = test("/* */1.2", nil)
- is(len(program.Body), 1)
- is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2")
- program = test("\n", nil)
- is(len(program.Body), 0)
- test(`
- if (0) {
- abc = 0
- }
- else abc = 0
- `, nil)
- test("if (0) abc = 0 else abc = 0", "(anonymous): Line 1:16 Unexpected token else")
- test(`
- if (0) {
- abc = 0
- } else abc = 0
- `, nil)
- test(`
- if (0) {
- abc = 1
- } else {
- }
- `, nil)
- test(`
- do {
- } while (true)
- `, nil)
- test(`
- try {
- } finally {
- }
- `, nil)
- test(`
- try {
- } catch (abc) {
- } finally {
- }
- `, nil)
- test(`
- try {
- }
- catch (abc) {
- }
- finally {
- }
- `, nil)
- test(`try {} catch (abc) {} finally {}`, nil)
- test("try {} catch {}", nil)
- test(`
- do {
- do {
- } while (0)
- } while (0)
- `, nil)
- test(`
- (function(){
- try {
- if (
- 1
- ) {
- return 1
- }
- return 0
- } finally {
- }
- })()
- `, nil)
- test("abc = ''\ndef", nil)
- test("abc = 1\ndef", nil)
- test("abc = Math\ndef", nil)
- test(`"\'"`, nil)
- test(`
- abc = function(){
- }
- abc = 0
- `, nil)
- test("abc.null = 0", nil)
- test("0x41", nil)
- test(`"\d"`, nil)
- test(`(function(){return this})`, nil)
- test(`
- Object.defineProperty(Array.prototype, "0", {
- value: 100,
- writable: false,
- configurable: true
- });
- abc = [101];
- abc.hasOwnProperty("0") && abc[0] === 101;
- `, nil)
- test(`new abc()`, nil)
- test(`new {}`, nil)
- test(`
- limit = 4
- result = 0
- while (limit) {
- limit = limit - 1
- if (limit) {
- }
- else {
- break
- }
- result = result + 1
- }
- `, nil)
- test(`
- while (0) {
- if (0) {
- continue
- }
- }
- `, nil)
- test("var \u0061\u0062\u0063 = 0", nil)
- // 7_3_1
- test("var test7_3_1\nabc = 66;", nil)
- test("var test7_3_1\u2028abc = 66;", nil)
- // 7_3_3
- test("//\u2028 =;", "(anonymous): Line 2:2 Unexpected token =")
- // 7_3_10
- test("var abc = \u2029;", "(anonymous): Line 2:1 Unexpected token ;")
- test("var abc = \\u2029;", "(anonymous): Line 1:11 Unexpected token ILLEGAL")
- test("var \\u0061\\u0062\\u0063 = 0;", nil)
- test("'", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- test("'\nstr\ning\n'", "(anonymous): Line 1:1 Unexpected token ILLEGAL")
- // S7.6_A4.3_T1
- test(`var $\u0030 = 0;`, nil)
- // S7.6.1.1_A1.1
- test(`switch = 1`, "(anonymous): Line 1:8 Unexpected token =")
- // S7.8.3_A2.1_T1
- test(`.0 === 0.0`, nil)
- // 7.8.5-1
- test("var regExp = /\\\rn/;", "(anonymous): Line 1:14 Invalid regular expression: missing /")
- // S7.8.5_A1.1_T2
- test("var regExp = /=/;", nil)
- // S7.8.5_A1.2_T1
- test("/*/", "(anonymous): Line 1:4 Unexpected end of input")
- // Sbp_7.9_A9_T3
- test(`
- do {
- ;
- } while (false) true
- `, nil)
- // S7.9_A10_T10
- test(`
- {a:1
- } 3
- `, nil)
- test(`
- abc
- ++def
- `, nil)
- // S7.9_A5.2_T1
- test(`
- for(false;false
- ) {
- break;
- }
- `, "(anonymous): Line 3:13 Unexpected token )")
- // S7.9_A9_T8
- test(`
- do {};
- while (false)
- `, "(anonymous): Line 2:18 Unexpected token ;")
- // S8.4_A5
- test(`
- "x\0y"
- `, nil)
- // S9.3.1_A6_T1
- test(`
- 10e10000
- `, nil)
- // 10.4.2-1-5
- test(`
- "abc\
- def"
- `, nil)
- test("'\\\n'", nil)
- test("'\\\r\n'", nil)
- //// 11.13.1-1-1
- test("42 = 42;", "(anonymous): Line 1:1 Invalid left-hand side in assignment")
- test("s &^= 42;", "(anonymous): Line 1:4 Unexpected token ^=")
- // S11.13.2_A4.2_T1.3
- test(`
- abc /= "1"
- `, nil)
- // 12.1-1
- test(`
- try{};catch(){}
- `, "(anonymous): Line 2:13 Missing catch or finally after try")
- // 12.1-3
- test(`
- try{};finally{}
- `, "(anonymous): Line 2:13 Missing catch or finally after try")
- // S12.6.3_A11.1_T3
- test(`
- while (true) {
- break abc;
- }
- `, "(anonymous): Line 3:17 Undefined label 'abc'")
- // S15.3_A2_T1
- test(`var x / = 1;`, "(anonymous): Line 1:7 Unexpected token /")
- test(`
- function abc() {
- if (0)
- return;
- else {
- }
- }
- `, nil)
- test("//\u2028 var =;", "(anonymous): Line 2:6 Unexpected token =")
- test(`
- throw
- {}
- `, "(anonymous): Line 2:13 Illegal newline after throw")
- // S7.6.1.1_A1.11
- test(`
- function = 1
- `, "(anonymous): Line 2:22 Unexpected token =")
- // S7.8.3_A1.2_T1
- test(`0e1`, nil)
- test("abc = 1; abc\n++", "(anonymous): Line 2:3 Unexpected end of input")
- // ---
- test("({ get abc() {} })", nil)
- test(`for (abc.def in {}) {}`, nil)
- test(`while (true) { break }`, nil)
- test(`while (true) { continue }`, nil)
- test(`abc=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,def=/^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/`, nil)
- test(`(function() { try {} catch (err) {} finally {} return })`, nil)
- test(`0xde0b6b3a7640080.toFixed(0)`, nil)
- test(`/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/`, nil)
- test(`/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]/`, nil)
- test("var abc = 1;\ufeff", nil)
- test("\ufeff/* var abc = 1; */", nil)
- test(`if (-0x8000000000000000<=abc&&abc<=0x8000000000000000) {}`, nil)
- test(`(function(){debugger;return this;})`, nil)
- test(`
- `, nil)
- test(`
- var abc = ""
- debugger
- `, nil)
- test(`
- var abc = /\[\]$/
- debugger
- `, nil)
- test(`
- var abc = 1 /
- 2
- debugger
- `, nil)
- test("'ё\\\u2029'", nil)
- test(`[a, b] = [1, 2]`, nil)
- test(`({"a b": {}} = {})`, nil)
- test(`ref = (a, b = 39,) => {
- };`, nil)
- test(`(a,) => {}`, nil)
- })
- }
- func TestParseDestruct(t *testing.T) {
- parser := newParser("", `({a: (a.b), ...spread,} = {})`)
- prg, err := parser.parse()
- if err != nil {
- t.Fatal(err)
- }
- _ = prg
- }
- func Test_parseStringLiteral(t *testing.T) {
- tt(t, func() {
- test := func(have string, want unistring.String) {
- parser := newParser("", have)
- parser.read()
- parser.read()
- _, res, err := parser.scanString(0, true)
- is(err, "")
- is(res, want)
- }
- test(`""`, "")
- test(`/=/`, "=")
- test("'1(\\\\d+)'", "1(\\d+)")
- test("'\\u2029'", "\u2029")
- test("'abc\\uFFFFabc'", "abc\uFFFFabc")
- test("'[First line \\\nSecond line \\\n Third line\\\n. ]'",
- "[First line Second line Third line. ]")
- test("'\\u007a\\x79\\u000a\\x78'", "zy\nx")
- // S7.8.4_A4.2_T3
- test("'\\a'", "a")
- test("'\u0410'", "\u0410")
- // S7.8.4_A5.1_T1
- test("'\\0'", "\u0000")
- // S8.4_A5
- test("'\u0000'", "\u0000")
- // 15.5.4.20
- test("\"'abc'\\\n'def'\"", "'abc''def'")
- // 15.5.4.20-4-1
- test("\"'abc'\\\r\n'def'\"", "'abc''def'")
- // Octal
- test("'\\0'", "\000")
- test("'\\00'", "\000")
- test("'\\000'", "\000")
- test("'\\09'", "\0009")
- test("'\\009'", "\0009")
- test("'\\0009'", "\0009")
- test("'\\1'", "\001")
- test("'\\01'", "\001")
- test("'\\001'", "\001")
- test("'\\0011'", "\0011")
- test("'\\1abc'", "\001abc")
- test("'\\\u4e16'", "\u4e16")
- // err
- test = func(have string, want unistring.String) {
- parser := newParser("", have)
- parser.read()
- parser.read()
- _, res, err := parser.scanString(0, true)
- is(err, want)
- is(res, "")
- }
- test(`"\u"`, `invalid escape: \u: len("") != 4`)
- test(`"\u0"`, `invalid escape: \u: len("0") != 4`)
- test(`"\u00"`, `invalid escape: \u: len("00") != 4`)
- test(`"\u000"`, `invalid escape: \u: len("000") != 4`)
- test(`"\x"`, `invalid escape: \x: len("") != 2`)
- test(`"\x0"`, `invalid escape: \x: len("0") != 2`)
- })
- }
- func Test_parseNumberLiteral(t *testing.T) {
- tt(t, func() {
- test := func(input string, expect interface{}) {
- result, err := parseNumberLiteral(input)
- is(err, nil)
- is(result, expect)
- }
- test("0", 0)
- test("0x8000000000000000", float64(9.223372036854776e+18))
- })
- }
- func TestPosition(t *testing.T) {
- tt(t, func() {
- parser := newParser("", "// Lorem ipsum")
- // Out of range, idx0 (error condition)
- is(parser.slice(0, 1), "")
- is(parser.slice(0, 10), "")
- // Out of range, idx1 (error condition)
- is(parser.slice(1, 128), "")
- is(parser.str[0:0], "")
- is(parser.slice(1, 1), "")
- is(parser.str[0:1], "/")
- is(parser.slice(1, 2), "/")
- is(parser.str[0:14], "// Lorem ipsum")
- is(parser.slice(1, 15), "// Lorem ipsum")
- parser = newParser("", "(function(){ return 0; })")
- program, err := parser.parse()
- is(err, nil)
- var node ast.Node
- node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral)
- is(node.Idx0(), file.Idx(2))
- is(node.Idx1(), file.Idx(25))
- is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }")
- is(parser.slice(node.Idx0(), node.Idx1()+1), "function(){ return 0; })")
- is(parser.slice(node.Idx0(), node.Idx1()+2), "")
- is(node.(*ast.FunctionLiteral).Source, "function(){ return 0; }")
- node = program
- is(node.Idx0(), file.Idx(2))
- is(node.Idx1(), file.Idx(25))
- is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }")
- parser = newParser("", "(function(){ return abc; })")
- program, err = parser.parse()
- is(err, nil)
- node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral)
- is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }")
- })
- }
- func TestExtractSourceMapLine(t *testing.T) {
- tt(t, func() {
- is(extractSourceMapLine(""), "")
- is(extractSourceMapLine("\n"), "")
- is(extractSourceMapLine(" "), "")
- is(extractSourceMapLine("1\n2\n3\n4\n"), "")
- src := `"use strict";
- var x = {};
- //# sourceMappingURL=delme.js.map`
- modSrc := `(function(exports, require, module) {` + src + `
- })`
- is(extractSourceMapLine(modSrc), "//# sourceMappingURL=delme.js.map")
- is(extractSourceMapLine(modSrc+"\n\n\n\n"), "//# sourceMappingURL=delme.js.map")
- })
- }
- func TestSourceMapOptions(t *testing.T) {
- tt(t, func() {
- count := 0
- requestedPath := ""
- loader := func(p string) ([]byte, error) {
- count++
- requestedPath = p
- return nil, nil
- }
- src := `"use strict";
- var x = {};
- //# sourceMappingURL=delme.js.map`
- _, err := ParseFile(nil, "delme.js", src, 0, WithSourceMapLoader(loader))
- is(err, nil)
- is(count, 1)
- is(requestedPath, "delme.js.map")
- count = 0
- _, err = ParseFile(nil, "", src, 0, WithSourceMapLoader(loader))
- is(err, nil)
- is(count, 1)
- is(requestedPath, "delme.js.map")
- count = 0
- _, err = ParseFile(nil, "delme.js", src, 0, WithDisableSourceMaps)
- is(err, nil)
- is(count, 0)
- _, err = ParseFile(nil, "/home/user/src/delme.js", src, 0, WithSourceMapLoader(loader))
- is(err, nil)
- is(count, 1)
- is(requestedPath, "/home/user/src/delme.js.map")
- count = 0
- _, err = ParseFile(nil, "https://site.com/delme.js", src, 0, WithSourceMapLoader(loader))
- is(err, nil)
- is(count, 1)
- is(requestedPath, "https://site.com/delme.js.map")
- })
- }
- func TestParseTemplateCharacters(t *testing.T) {
- parser := newParser("", "`test\\\r\\\n${a}`")
- parser.next()
- if parser.token != token.BACKTICK {
- t.Fatalf("Token: %s", parser.token)
- }
- checkParseTemplateChars := func(expectedLiteral string, expectedParsed unistring.String, expectedFinished, expectParseErr, expectErr bool) {
- literal, parsed, finished, parseErr, err := parser.parseTemplateCharacters()
- if err != "" != expectErr {
- t.Fatal(err)
- }
- if literal != expectedLiteral {
- t.Fatalf("Literal: %q", literal)
- }
- if parsed != expectedParsed {
- t.Fatalf("Parsed: %q", parsed)
- }
- if finished != expectedFinished {
- t.Fatal(finished)
- }
- if parseErr != "" != expectParseErr {
- t.Fatalf("parseErr: %v", parseErr)
- }
- }
- checkParseTemplateChars("test\\\n\\\n", "test", false, false, false)
- parser.next()
- parser.expect(token.IDENTIFIER)
- if len(parser.errors) > 0 {
- t.Fatal(parser.errors)
- }
- if parser.token != token.RIGHT_BRACE {
- t.Fatal("Expected }")
- }
- if len(parser.errors) > 0 {
- t.Fatal(parser.errors)
- }
- checkParseTemplateChars("", "", true, false, false)
- if parser.chr != -1 {
- t.Fatal("Expected EOF")
- }
- }
- func TestParseTemplateLiteral(t *testing.T) {
- parser := newParser("", "f()\n`test${a}`")
- prg, err := parser.parse()
- if err != nil {
- t.Fatal(err)
- }
- if st, ok := prg.Body[0].(*ast.ExpressionStatement); ok {
- if expr, ok := st.Expression.(*ast.TemplateLiteral); ok {
- if expr.Tag == nil {
- t.Fatal("tag is nil")
- }
- if idx0 := expr.Tag.Idx0(); idx0 != 1 {
- t.Fatalf("Tag.Idx0(): %d", idx0)
- }
- if expr.OpenQuote != 5 {
- t.Fatalf("OpenQuote: %d", expr.OpenQuote)
- }
- if expr.CloseQuote != 14 {
- t.Fatalf("CloseQuote: %d", expr.CloseQuote)
- }
- if l := len(expr.Elements); l != 2 {
- t.Fatalf("len elements: %d", l)
- }
- if l := len(expr.Expressions); l != 1 {
- t.Fatalf("len expressions: %d", l)
- }
- } else {
- t.Fatal(st)
- }
- } else {
- t.Fatal(prg.Body[0])
- }
- }
- func TestParseTemplateLiteralWithTail(t *testing.T) {
- parser := newParser("", "f()\n`test${a}tail` ")
- prg, err := parser.parse()
- if err != nil {
- t.Fatal(err)
- }
- if st, ok := prg.Body[0].(*ast.ExpressionStatement); ok {
- if expr, ok := st.Expression.(*ast.TemplateLiteral); ok {
- if expr.CloseQuote != 18 {
- t.Fatalf("CloseQuote: %d", expr.CloseQuote)
- }
- } else {
- t.Fatal(st)
- }
- } else {
- t.Fatal(prg.Body[0])
- }
- }
|