marshal_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. package parser
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "reflect"
  6. "strings"
  7. "testing"
  8. "github.com/dop251/goja/ast"
  9. )
  10. func marshal(name string, children ...interface{}) interface{} {
  11. if len(children) == 1 {
  12. if name == "" {
  13. return testMarshalNode(children[0])
  14. }
  15. return map[string]interface{}{
  16. name: children[0],
  17. }
  18. }
  19. map_ := map[string]interface{}{}
  20. length := len(children) / 2
  21. for i := 0; i < length; i++ {
  22. name := children[i*2].(string)
  23. value := children[i*2+1]
  24. map_[name] = value
  25. }
  26. if name == "" {
  27. return map_
  28. }
  29. return map[string]interface{}{
  30. name: map_,
  31. }
  32. }
  33. func testMarshalNode(node interface{}) interface{} {
  34. switch node := node.(type) {
  35. // Expression
  36. case *ast.ArrayLiteral:
  37. return marshal("Array", testMarshalNode(node.Value))
  38. case *ast.AssignExpression:
  39. return marshal("Assign",
  40. "Left", testMarshalNode(node.Left),
  41. "Right", testMarshalNode(node.Right),
  42. )
  43. case *ast.BinaryExpression:
  44. return marshal("BinaryExpression",
  45. "Operator", node.Operator.String(),
  46. "Left", testMarshalNode(node.Left),
  47. "Right", testMarshalNode(node.Right),
  48. )
  49. case *ast.BooleanLiteral:
  50. return marshal("Literal", node.Value)
  51. case *ast.CallExpression:
  52. return marshal("Call",
  53. "Callee", testMarshalNode(node.Callee),
  54. "ArgumentList", testMarshalNode(node.ArgumentList),
  55. )
  56. case *ast.ConditionalExpression:
  57. return marshal("Conditional",
  58. "Test", testMarshalNode(node.Test),
  59. "Consequent", testMarshalNode(node.Consequent),
  60. "Alternate", testMarshalNode(node.Alternate),
  61. )
  62. case *ast.DotExpression:
  63. return marshal("Dot",
  64. "Left", testMarshalNode(node.Left),
  65. "Member", node.Identifier.Name,
  66. )
  67. case *ast.NewExpression:
  68. return marshal("New",
  69. "Callee", testMarshalNode(node.Callee),
  70. "ArgumentList", testMarshalNode(node.ArgumentList),
  71. )
  72. case *ast.NullLiteral:
  73. return marshal("Literal", nil)
  74. case *ast.NumberLiteral:
  75. return marshal("Literal", node.Value)
  76. case *ast.ObjectLiteral:
  77. return marshal("Object", testMarshalNode(node.Value))
  78. case *ast.RegExpLiteral:
  79. return marshal("Literal", node.Literal)
  80. case *ast.StringLiteral:
  81. return marshal("Literal", node.Literal)
  82. case *ast.VariableExpression:
  83. return []interface{}{node.Name, testMarshalNode(node.Initializer)}
  84. // Statement
  85. case *ast.Program:
  86. return testMarshalNode(node.Body)
  87. case *ast.BlockStatement:
  88. return marshal("BlockStatement", testMarshalNode(node.List))
  89. case *ast.EmptyStatement:
  90. return "EmptyStatement"
  91. case *ast.ExpressionStatement:
  92. return testMarshalNode(node.Expression)
  93. case *ast.ForInStatement:
  94. return marshal("ForIn",
  95. "Into", marshal("", node.Into),
  96. "Source", marshal("", node.Source),
  97. "Body", marshal("", node.Body),
  98. )
  99. case *ast.FunctionLiteral:
  100. return marshal("Function", testMarshalNode(node.Body))
  101. case *ast.Identifier:
  102. return marshal("Identifier", node.Name)
  103. case *ast.IfStatement:
  104. if_ := marshal("",
  105. "Test", testMarshalNode(node.Test),
  106. "Consequent", testMarshalNode(node.Consequent),
  107. ).(map[string]interface{})
  108. if node.Alternate != nil {
  109. if_["Alternate"] = testMarshalNode(node.Alternate)
  110. }
  111. return marshal("If", if_)
  112. case *ast.LabelledStatement:
  113. return marshal("Label",
  114. "Name", node.Label.Name,
  115. "Statement", testMarshalNode(node.Statement),
  116. )
  117. case ast.Property:
  118. return marshal("",
  119. "Key", node.Key,
  120. "Value", testMarshalNode(node.Value),
  121. )
  122. case *ast.ReturnStatement:
  123. return marshal("Return", testMarshalNode(node.Argument))
  124. case *ast.SequenceExpression:
  125. return marshal("Sequence", testMarshalNode(node.Sequence))
  126. case *ast.ThrowStatement:
  127. return marshal("Throw", testMarshalNode(node.Argument))
  128. case *ast.VariableStatement:
  129. return marshal("Var", testMarshalNode(node.List))
  130. }
  131. {
  132. value := reflect.ValueOf(node)
  133. if value.Kind() == reflect.Slice {
  134. tmp0 := []interface{}{}
  135. for index := 0; index < value.Len(); index++ {
  136. tmp0 = append(tmp0, testMarshalNode(value.Index(index).Interface()))
  137. }
  138. return tmp0
  139. }
  140. }
  141. return nil
  142. }
  143. func testMarshal(node interface{}) string {
  144. value, err := json.Marshal(testMarshalNode(node))
  145. if err != nil {
  146. panic(err)
  147. }
  148. return string(value)
  149. }
  150. func TestParserAST(t *testing.T) {
  151. tt(t, func() {
  152. test := func(inputOutput string) {
  153. match := matchBeforeAfterSeparator.FindStringIndex(inputOutput)
  154. input := strings.TrimSpace(inputOutput[0:match[0]])
  155. wantOutput := strings.TrimSpace(inputOutput[match[1]:])
  156. _, program, err := testParse(input)
  157. is(err, nil)
  158. haveOutput := testMarshal(program)
  159. tmp0, tmp1 := bytes.Buffer{}, bytes.Buffer{}
  160. json.Indent(&tmp0, []byte(haveOutput), "\t\t", " ")
  161. json.Indent(&tmp1, []byte(wantOutput), "\t\t", " ")
  162. is("\n\t\t"+tmp0.String(), "\n\t\t"+tmp1.String())
  163. }
  164. test(`
  165. ---
  166. []
  167. `)
  168. test(`
  169. ;
  170. ---
  171. [
  172. "EmptyStatement"
  173. ]
  174. `)
  175. test(`
  176. ;;;
  177. ---
  178. [
  179. "EmptyStatement",
  180. "EmptyStatement",
  181. "EmptyStatement"
  182. ]
  183. `)
  184. test(`
  185. 1; true; abc; "abc"; null;
  186. ---
  187. [
  188. {
  189. "Literal": 1
  190. },
  191. {
  192. "Literal": true
  193. },
  194. {
  195. "Identifier": "abc"
  196. },
  197. {
  198. "Literal": "\"abc\""
  199. },
  200. {
  201. "Literal": null
  202. }
  203. ]
  204. `)
  205. test(`
  206. { 1; null; 3.14159; ; }
  207. ---
  208. [
  209. {
  210. "BlockStatement": [
  211. {
  212. "Literal": 1
  213. },
  214. {
  215. "Literal": null
  216. },
  217. {
  218. "Literal": 3.14159
  219. },
  220. "EmptyStatement"
  221. ]
  222. }
  223. ]
  224. `)
  225. test(`
  226. new abc();
  227. ---
  228. [
  229. {
  230. "New": {
  231. "ArgumentList": [],
  232. "Callee": {
  233. "Identifier": "abc"
  234. }
  235. }
  236. }
  237. ]
  238. `)
  239. test(`
  240. new abc(1, 3.14159)
  241. ---
  242. [
  243. {
  244. "New": {
  245. "ArgumentList": [
  246. {
  247. "Literal": 1
  248. },
  249. {
  250. "Literal": 3.14159
  251. }
  252. ],
  253. "Callee": {
  254. "Identifier": "abc"
  255. }
  256. }
  257. }
  258. ]
  259. `)
  260. test(`
  261. true ? false : true
  262. ---
  263. [
  264. {
  265. "Conditional": {
  266. "Alternate": {
  267. "Literal": true
  268. },
  269. "Consequent": {
  270. "Literal": false
  271. },
  272. "Test": {
  273. "Literal": true
  274. }
  275. }
  276. }
  277. ]
  278. `)
  279. test(`
  280. true || false
  281. ---
  282. [
  283. {
  284. "BinaryExpression": {
  285. "Left": {
  286. "Literal": true
  287. },
  288. "Operator": "||",
  289. "Right": {
  290. "Literal": false
  291. }
  292. }
  293. }
  294. ]
  295. `)
  296. test(`
  297. 0 + { abc: true }
  298. ---
  299. [
  300. {
  301. "BinaryExpression": {
  302. "Left": {
  303. "Literal": 0
  304. },
  305. "Operator": "+",
  306. "Right": {
  307. "Object": [
  308. {
  309. "Key": {
  310. "Idx": 7,
  311. "Literal": "abc",
  312. "Value": "abc"
  313. },
  314. "Value": {
  315. "Literal": true
  316. }
  317. }
  318. ]
  319. }
  320. }
  321. }
  322. ]
  323. `)
  324. test(`
  325. 1 == "1"
  326. ---
  327. [
  328. {
  329. "BinaryExpression": {
  330. "Left": {
  331. "Literal": 1
  332. },
  333. "Operator": "==",
  334. "Right": {
  335. "Literal": "\"1\""
  336. }
  337. }
  338. }
  339. ]
  340. `)
  341. test(`
  342. abc(1)
  343. ---
  344. [
  345. {
  346. "Call": {
  347. "ArgumentList": [
  348. {
  349. "Literal": 1
  350. }
  351. ],
  352. "Callee": {
  353. "Identifier": "abc"
  354. }
  355. }
  356. }
  357. ]
  358. `)
  359. test(`
  360. Math.pow(3, 2)
  361. ---
  362. [
  363. {
  364. "Call": {
  365. "ArgumentList": [
  366. {
  367. "Literal": 3
  368. },
  369. {
  370. "Literal": 2
  371. }
  372. ],
  373. "Callee": {
  374. "Dot": {
  375. "Left": {
  376. "Identifier": "Math"
  377. },
  378. "Member": "pow"
  379. }
  380. }
  381. }
  382. }
  383. ]
  384. `)
  385. test(`
  386. 1, 2, 3
  387. ---
  388. [
  389. {
  390. "Sequence": [
  391. {
  392. "Literal": 1
  393. },
  394. {
  395. "Literal": 2
  396. },
  397. {
  398. "Literal": 3
  399. }
  400. ]
  401. }
  402. ]
  403. `)
  404. test(`
  405. / abc /gim;
  406. ---
  407. [
  408. {
  409. "Literal": "/ abc /gim"
  410. }
  411. ]
  412. `)
  413. test(`
  414. if (0)
  415. 1;
  416. ---
  417. [
  418. {
  419. "If": {
  420. "Consequent": {
  421. "Literal": 1
  422. },
  423. "Test": {
  424. "Literal": 0
  425. }
  426. }
  427. }
  428. ]
  429. `)
  430. test(`
  431. 0+function(){
  432. return;
  433. }
  434. ---
  435. [
  436. {
  437. "BinaryExpression": {
  438. "Left": {
  439. "Literal": 0
  440. },
  441. "Operator": "+",
  442. "Right": {
  443. "Function": {
  444. "BlockStatement": [
  445. {
  446. "Return": null
  447. }
  448. ]
  449. }
  450. }
  451. }
  452. }
  453. ]
  454. `)
  455. test(`
  456. xyzzy // Ignore it
  457. // Ignore this
  458. // And this
  459. /* And all..
  460. ... of this!
  461. */
  462. "Nothing happens."
  463. // And finally this
  464. ---
  465. [
  466. {
  467. "Identifier": "xyzzy"
  468. },
  469. {
  470. "Literal": "\"Nothing happens.\""
  471. }
  472. ]
  473. `)
  474. test(`
  475. ((x & (x = 1)) !== 0)
  476. ---
  477. [
  478. {
  479. "BinaryExpression": {
  480. "Left": {
  481. "BinaryExpression": {
  482. "Left": {
  483. "Identifier": "x"
  484. },
  485. "Operator": "\u0026",
  486. "Right": {
  487. "Assign": {
  488. "Left": {
  489. "Identifier": "x"
  490. },
  491. "Right": {
  492. "Literal": 1
  493. }
  494. }
  495. }
  496. }
  497. },
  498. "Operator": "!==",
  499. "Right": {
  500. "Literal": 0
  501. }
  502. }
  503. }
  504. ]
  505. `)
  506. test(`
  507. { abc: 'def' }
  508. ---
  509. [
  510. {
  511. "BlockStatement": [
  512. {
  513. "Label": {
  514. "Name": "abc",
  515. "Statement": {
  516. "Literal": "'def'"
  517. }
  518. }
  519. }
  520. ]
  521. }
  522. ]
  523. `)
  524. test(`
  525. // This is not an object, this is a string literal with a label!
  526. ({ abc: 'def' })
  527. ---
  528. [
  529. {
  530. "Object": [
  531. {
  532. "Key": {
  533. "Idx": 77,
  534. "Literal": "abc",
  535. "Value": "abc"
  536. },
  537. "Value": {
  538. "Literal": "'def'"
  539. }
  540. }
  541. ]
  542. }
  543. ]
  544. `)
  545. test(`
  546. [,]
  547. ---
  548. [
  549. {
  550. "Array": [
  551. null
  552. ]
  553. }
  554. ]
  555. `)
  556. test(`
  557. [,,]
  558. ---
  559. [
  560. {
  561. "Array": [
  562. null,
  563. null
  564. ]
  565. }
  566. ]
  567. `)
  568. test(`
  569. ({ get abc() {} })
  570. ---
  571. [
  572. {
  573. "Object": [
  574. {
  575. "Key": {
  576. "Idx": 8,
  577. "Literal": "abc",
  578. "Value": "abc"
  579. },
  580. "Value": {
  581. "Function": {
  582. "BlockStatement": []
  583. }
  584. }
  585. }
  586. ]
  587. }
  588. ]
  589. `)
  590. test(`
  591. /abc/.source
  592. ---
  593. [
  594. {
  595. "Dot": {
  596. "Left": {
  597. "Literal": "/abc/"
  598. },
  599. "Member": "source"
  600. }
  601. }
  602. ]
  603. `)
  604. test(`
  605. xyzzy
  606. throw new TypeError("Nothing happens.")
  607. ---
  608. [
  609. {
  610. "Identifier": "xyzzy"
  611. },
  612. {
  613. "Throw": {
  614. "New": {
  615. "ArgumentList": [
  616. {
  617. "Literal": "\"Nothing happens.\""
  618. }
  619. ],
  620. "Callee": {
  621. "Identifier": "TypeError"
  622. }
  623. }
  624. }
  625. }
  626. ]
  627. `)
  628. // When run, this will call a type error to be thrown
  629. // This is essentially the same as:
  630. //
  631. // var abc = 1(function(){})()
  632. //
  633. test(`
  634. var abc = 1
  635. (function(){
  636. })()
  637. ---
  638. [
  639. {
  640. "Var": [
  641. [
  642. "abc",
  643. {
  644. "Call": {
  645. "ArgumentList": [],
  646. "Callee": {
  647. "Call": {
  648. "ArgumentList": [
  649. {
  650. "Function": {
  651. "BlockStatement": []
  652. }
  653. }
  654. ],
  655. "Callee": {
  656. "Literal": 1
  657. }
  658. }
  659. }
  660. }
  661. }
  662. ]
  663. ]
  664. }
  665. ]
  666. `)
  667. test(`
  668. "use strict"
  669. ---
  670. [
  671. {
  672. "Literal": "\"use strict\""
  673. }
  674. ]
  675. `)
  676. test(`
  677. "use strict"
  678. abc = 1 + 2 + 11
  679. ---
  680. [
  681. {
  682. "Literal": "\"use strict\""
  683. },
  684. {
  685. "Assign": {
  686. "Left": {
  687. "Identifier": "abc"
  688. },
  689. "Right": {
  690. "BinaryExpression": {
  691. "Left": {
  692. "BinaryExpression": {
  693. "Left": {
  694. "Literal": 1
  695. },
  696. "Operator": "+",
  697. "Right": {
  698. "Literal": 2
  699. }
  700. }
  701. },
  702. "Operator": "+",
  703. "Right": {
  704. "Literal": 11
  705. }
  706. }
  707. }
  708. }
  709. }
  710. ]
  711. `)
  712. test(`
  713. abc = function() { 'use strict' }
  714. ---
  715. [
  716. {
  717. "Assign": {
  718. "Left": {
  719. "Identifier": "abc"
  720. },
  721. "Right": {
  722. "Function": {
  723. "BlockStatement": [
  724. {
  725. "Literal": "'use strict'"
  726. }
  727. ]
  728. }
  729. }
  730. }
  731. }
  732. ]
  733. `)
  734. test(`
  735. for (var abc in def) {
  736. }
  737. ---
  738. [
  739. {
  740. "ForIn": {
  741. "Body": {
  742. "BlockStatement": []
  743. },
  744. "Into": [
  745. "abc",
  746. null
  747. ],
  748. "Source": {
  749. "Identifier": "def"
  750. }
  751. }
  752. }
  753. ]
  754. `)
  755. test(`
  756. abc = {
  757. '"': "'",
  758. "'": '"',
  759. }
  760. ---
  761. [
  762. {
  763. "Assign": {
  764. "Left": {
  765. "Identifier": "abc"
  766. },
  767. "Right": {
  768. "Object": [
  769. {
  770. "Key": {
  771. "Idx": 21,
  772. "Literal": "'\"'",
  773. "Value": "\""
  774. },
  775. "Value": {
  776. "Literal": "\"'\""
  777. }
  778. },
  779. {
  780. "Key": {
  781. "Idx": 43,
  782. "Literal": "\"'\"",
  783. "Value": "'"
  784. },
  785. "Value": {
  786. "Literal": "'\"'"
  787. }
  788. }
  789. ]
  790. }
  791. }
  792. }
  793. ]
  794. `)
  795. return
  796. test(`
  797. if (!abc && abc.jkl(def) && abc[0] === +abc[0] && abc.length < ghi) {
  798. }
  799. ---
  800. [
  801. {
  802. "If": {
  803. "Consequent": {
  804. "BlockStatement": []
  805. },
  806. "Test": {
  807. "BinaryExpression": {
  808. "Left": {
  809. "BinaryExpression": {
  810. "Left": {
  811. "BinaryExpression": {
  812. "Left": null,
  813. "Operator": "\u0026\u0026",
  814. "Right": {
  815. "Call": {
  816. "ArgumentList": [
  817. {
  818. "Identifier": "def"
  819. }
  820. ],
  821. "Callee": {
  822. "Dot": {
  823. "Left": {
  824. "Identifier": "abc"
  825. },
  826. "Member": "jkl"
  827. }
  828. }
  829. }
  830. }
  831. }
  832. },
  833. "Operator": "\u0026\u0026",
  834. "Right": {
  835. "BinaryExpression": {
  836. "Left": null,
  837. "Operator": "===",
  838. "Right": null
  839. }
  840. }
  841. }
  842. },
  843. "Operator": "\u0026\u0026",
  844. "Right": {
  845. "BinaryExpression": {
  846. "Left": {
  847. "Dot": {
  848. "Left": {
  849. "Identifier": "abc"
  850. },
  851. "Member": "length"
  852. }
  853. },
  854. "Operator": "\u003c",
  855. "Right": {
  856. "Identifier": "ghi"
  857. }
  858. }
  859. }
  860. }
  861. }
  862. }
  863. }
  864. ]
  865. `)
  866. })
  867. }