runtime_test.go 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. package goja
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. "testing"
  7. "time"
  8. )
  9. func TestGlobalObjectProto(t *testing.T) {
  10. const SCRIPT = `
  11. this instanceof Object
  12. `
  13. testScript1(SCRIPT, valueTrue, t)
  14. }
  15. func TestArrayProtoProp(t *testing.T) {
  16. const SCRIPT = `
  17. Object.defineProperty(Array.prototype, '0', {value: 42, configurable: true, writable: false})
  18. var a = []
  19. a[0] = 1
  20. a[0]
  21. `
  22. testScript1(SCRIPT, valueInt(42), t)
  23. }
  24. func TestArrayDelete(t *testing.T) {
  25. const SCRIPT = `
  26. var a = [1, 2];
  27. var deleted = delete a[0];
  28. var undef = a[0] === undefined;
  29. var len = a.length;
  30. deleted && undef && len === 2;
  31. `
  32. testScript1(SCRIPT, valueTrue, t)
  33. }
  34. func TestArrayDeleteNonexisting(t *testing.T) {
  35. const SCRIPT = `
  36. Array.prototype[0] = 42;
  37. var a = [];
  38. delete a[0] && a[0] === 42;
  39. `
  40. testScript1(SCRIPT, valueTrue, t)
  41. }
  42. func TestArraySetLength(t *testing.T) {
  43. const SCRIPT = `
  44. var a = [1, 2];
  45. var assert0 = a.length == 2;
  46. a.length = "1";
  47. a.length = 1.0;
  48. a.length = 1;
  49. var assert1 = a.length == 1;
  50. a.length = 2;
  51. var assert2 = a.length == 2;
  52. assert0 && assert1 && assert2 && a[1] === undefined;
  53. `
  54. testScript1(SCRIPT, valueTrue, t)
  55. }
  56. func TestUnicodeString(t *testing.T) {
  57. const SCRIPT = `
  58. var s = "Тест";
  59. s.length === 4 && s[1] === "е";
  60. `
  61. testScript1(SCRIPT, valueTrue, t)
  62. }
  63. func TestArrayReverseNonOptimisable(t *testing.T) {
  64. const SCRIPT = `
  65. var a = [];
  66. Object.defineProperty(a, "0", {get: function() {return 42}, set: function(v) {Object.defineProperty(a, "0", {value: v + 1, writable: true, configurable: true})}, configurable: true})
  67. a[1] = 43;
  68. a.reverse();
  69. a.length === 2 && a[0] === 44 && a[1] === 42;
  70. `
  71. testScript1(SCRIPT, valueTrue, t)
  72. }
  73. func TestArrayPushNonOptimisable(t *testing.T) {
  74. const SCRIPT = `
  75. Object.defineProperty(Object.prototype, "0", {value: 42});
  76. var a = [];
  77. var thrown = false;
  78. try {
  79. a.push(1);
  80. } catch (e) {
  81. thrown = e instanceof TypeError;
  82. }
  83. thrown;
  84. `
  85. testScript1(SCRIPT, valueTrue, t)
  86. }
  87. func TestArraySetLengthWithPropItems(t *testing.T) {
  88. const SCRIPT = `
  89. var a = [1,2,3,4];
  90. var thrown = false;
  91. Object.defineProperty(a, "2", {value: 42, configurable: false, writable: false});
  92. try {
  93. Object.defineProperty(a, "length", {value: 0, writable: false});
  94. } catch (e) {
  95. thrown = e instanceof TypeError;
  96. }
  97. thrown && a.length === 3;
  98. `
  99. testScript1(SCRIPT, valueTrue, t)
  100. }
  101. func Test2TierHierarchyProp(t *testing.T) {
  102. const SCRIPT = `
  103. var a = {};
  104. Object.defineProperty(a, "test", {
  105. value: 42,
  106. writable: false,
  107. enumerable: false,
  108. configurable: true
  109. });
  110. var b = Object.create(a);
  111. var c = Object.create(b);
  112. c.test = 43;
  113. c.test === 42 && !b.hasOwnProperty("test");
  114. `
  115. testScript1(SCRIPT, valueTrue, t)
  116. }
  117. func TestConstStringIter(t *testing.T) {
  118. const SCRIPT = `
  119. var count = 0;
  120. for (var i in "1234") {
  121. for (var j in "1234567") {
  122. count++
  123. }
  124. }
  125. count;
  126. `
  127. testScript1(SCRIPT, intToValue(28), t)
  128. }
  129. func TestUnicodeConcat(t *testing.T) {
  130. const SCRIPT = `
  131. var s = "тест";
  132. var s1 = "test";
  133. var s2 = "абвгд";
  134. s.concat(s1) === "тестtest" && s.concat(s1, s2) === "тестtestабвгд" && s1.concat(s, s2) === "testтестабвгд"
  135. && s.concat(s2) === "тестабвгд";
  136. `
  137. testScript1(SCRIPT, valueTrue, t)
  138. }
  139. func TestIndexOf(t *testing.T) {
  140. const SCRIPT = `
  141. "abc".indexOf("", 4)
  142. `
  143. testScript1(SCRIPT, intToValue(3), t)
  144. }
  145. func TestUnicodeIndexOf(t *testing.T) {
  146. const SCRIPT = `
  147. "абвгд".indexOf("вг", 1) === 2 && '中国'.indexOf('国') === 1
  148. `
  149. testScript1(SCRIPT, valueTrue, t)
  150. }
  151. func TestLastIndexOf(t *testing.T) {
  152. const SCRIPT = `
  153. "abcabab".lastIndexOf("ab", 3)
  154. `
  155. testScript1(SCRIPT, intToValue(3), t)
  156. }
  157. func TestUnicodeLastIndexOf(t *testing.T) {
  158. const SCRIPT = `
  159. "абвабаб".lastIndexOf("аб", 3)
  160. `
  161. testScript1(SCRIPT, intToValue(3), t)
  162. }
  163. func TestUnicodeLastIndexOf1(t *testing.T) {
  164. const SCRIPT = `
  165. "abꞐcde".lastIndexOf("cd");
  166. `
  167. testScript1(SCRIPT, intToValue(3), t)
  168. }
  169. func TestNumber(t *testing.T) {
  170. const SCRIPT = `
  171. (new Number(100111122133144155)).toString()
  172. `
  173. testScript1(SCRIPT, asciiString("100111122133144160"), t)
  174. }
  175. func TestFractionalNumberToStringRadix(t *testing.T) {
  176. const SCRIPT = `
  177. (new Number(123.456)).toString(36)
  178. `
  179. testScript1(SCRIPT, asciiString("3f.gez4w97ry"), t)
  180. }
  181. func TestSetFunc(t *testing.T) {
  182. const SCRIPT = `
  183. sum(40, 2);
  184. `
  185. r := New()
  186. r.Set("sum", func(call FunctionCall) Value {
  187. return r.ToValue(call.Argument(0).ToInteger() + call.Argument(1).ToInteger())
  188. })
  189. v, err := r.RunString(SCRIPT)
  190. if err != nil {
  191. t.Fatal(err)
  192. }
  193. if i := v.ToInteger(); i != 42 {
  194. t.Fatalf("Expected 42, got: %d", i)
  195. }
  196. }
  197. func TestObjectGetSet(t *testing.T) {
  198. const SCRIPT = `
  199. input.test++;
  200. input;
  201. `
  202. r := New()
  203. o := r.NewObject()
  204. o.Set("test", 42)
  205. r.Set("input", o)
  206. v, err := r.RunString(SCRIPT)
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. if o1, ok := v.(*Object); ok {
  211. if v1 := o1.Get("test"); v1.Export() != int64(43) {
  212. t.Fatalf("Unexpected test value: %v (%T)", v1, v1.Export())
  213. }
  214. }
  215. }
  216. func TestThrowFromNativeFunc(t *testing.T) {
  217. const SCRIPT = `
  218. var thrown;
  219. try {
  220. f();
  221. } catch (e) {
  222. thrown = e;
  223. }
  224. thrown;
  225. `
  226. r := New()
  227. r.Set("f", func(call FunctionCall) Value {
  228. panic(r.ToValue("testError"))
  229. })
  230. v, err := r.RunString(SCRIPT)
  231. if err != nil {
  232. t.Fatal(err)
  233. }
  234. if !v.Equals(asciiString("testError")) {
  235. t.Fatalf("Unexpected result: %v", v)
  236. }
  237. }
  238. func TestSetGoFunc(t *testing.T) {
  239. const SCRIPT = `
  240. f(40, 2)
  241. `
  242. r := New()
  243. r.Set("f", func(a, b int) int {
  244. return a + b
  245. })
  246. v, err := r.RunString(SCRIPT)
  247. if err != nil {
  248. t.Fatal(err)
  249. }
  250. if v.ToInteger() != 42 {
  251. t.Fatalf("Unexpected result: %v", v)
  252. }
  253. }
  254. func TestArgsKeys(t *testing.T) {
  255. const SCRIPT = `
  256. function testArgs2(x, y, z) {
  257. // Properties of the arguments object are enumerable.
  258. return Object.keys(arguments);
  259. }
  260. testArgs2(1,2).length
  261. `
  262. testScript1(SCRIPT, intToValue(2), t)
  263. }
  264. func TestIPowOverflow(t *testing.T) {
  265. const SCRIPT = `
  266. Math.pow(65536, 6)
  267. `
  268. testScript1(SCRIPT, floatToValue(7.922816251426434e+28), t)
  269. }
  270. func TestIPowZero(t *testing.T) {
  271. const SCRIPT = `
  272. Math.pow(0, 0)
  273. `
  274. testScript1(SCRIPT, intToValue(1), t)
  275. }
  276. func TestInterrupt(t *testing.T) {
  277. const SCRIPT = `
  278. var i = 0;
  279. for (;;) {
  280. i++;
  281. }
  282. `
  283. vm := New()
  284. time.AfterFunc(200*time.Millisecond, func() {
  285. vm.Interrupt("halt")
  286. })
  287. _, err := vm.RunString(SCRIPT)
  288. if err == nil {
  289. t.Fatal("Err is nil")
  290. }
  291. }
  292. func TestRuntime_ExportToSlice(t *testing.T) {
  293. const SCRIPT = `
  294. var a = [1, 2, 3];
  295. a;
  296. `
  297. vm := New()
  298. v, err := vm.RunString(SCRIPT)
  299. if err != nil {
  300. t.Fatal(err)
  301. }
  302. var a []string
  303. err = vm.ExportTo(v, &a)
  304. if err != nil {
  305. t.Fatal(err)
  306. }
  307. if l := len(a); l != 3 {
  308. t.Fatalf("Unexpected len: %d", l)
  309. }
  310. if a[0] != "1" || a[1] != "2" || a[2] != "3" {
  311. t.Fatalf("Unexpected value: %+v", a)
  312. }
  313. }
  314. func TestRuntime_ExportToMap(t *testing.T) {
  315. const SCRIPT = `
  316. var m = {
  317. "0": 1,
  318. "1": 2,
  319. "2": 3,
  320. }
  321. m;
  322. `
  323. vm := New()
  324. v, err := vm.RunString(SCRIPT)
  325. if err != nil {
  326. t.Fatal(err)
  327. }
  328. var m map[int]string
  329. err = vm.ExportTo(v, &m)
  330. if err != nil {
  331. t.Fatal(err)
  332. }
  333. if l := len(m); l != 3 {
  334. t.Fatalf("Unexpected len: %d", l)
  335. }
  336. if m[0] != "1" || m[1] != "2" || m[2] != "3" {
  337. t.Fatalf("Unexpected value: %+v", m)
  338. }
  339. }
  340. func TestRuntime_ExportToMap1(t *testing.T) {
  341. const SCRIPT = `
  342. var m = {
  343. "0": 1,
  344. "1": 2,
  345. "2": 3,
  346. }
  347. m;
  348. `
  349. vm := New()
  350. v, err := vm.RunString(SCRIPT)
  351. if err != nil {
  352. t.Fatal(err)
  353. }
  354. var m map[string]string
  355. err = vm.ExportTo(v, &m)
  356. if err != nil {
  357. t.Fatal(err)
  358. }
  359. if l := len(m); l != 3 {
  360. t.Fatalf("Unexpected len: %d", l)
  361. }
  362. if m["0"] != "1" || m["1"] != "2" || m["2"] != "3" {
  363. t.Fatalf("Unexpected value: %+v", m)
  364. }
  365. }
  366. func TestRuntime_ExportToStruct(t *testing.T) {
  367. const SCRIPT = `
  368. var m = {
  369. Test: 1,
  370. }
  371. m;
  372. `
  373. vm := New()
  374. v, err := vm.RunString(SCRIPT)
  375. if err != nil {
  376. t.Fatal(err)
  377. }
  378. var o testGoReflectMethod_O
  379. err = vm.ExportTo(v, &o)
  380. if err != nil {
  381. t.Fatal(err)
  382. }
  383. if o.Test != "1" {
  384. t.Fatalf("Unexpected value: '%s'", o.Test)
  385. }
  386. }
  387. func TestRuntime_ExportToStructPtr(t *testing.T) {
  388. const SCRIPT = `
  389. var m = {
  390. Test: 1,
  391. }
  392. m;
  393. `
  394. vm := New()
  395. v, err := vm.RunString(SCRIPT)
  396. if err != nil {
  397. t.Fatal(err)
  398. }
  399. var o *testGoReflectMethod_O
  400. err = vm.ExportTo(v, &o)
  401. if err != nil {
  402. t.Fatal(err)
  403. }
  404. if o.Test != "1" {
  405. t.Fatalf("Unexpected value: '%s'", o.Test)
  406. }
  407. }
  408. func TestRuntime_ExportToStructAnonymous(t *testing.T) {
  409. type BaseTestStruct struct {
  410. A int64
  411. B int64
  412. }
  413. type TestStruct struct {
  414. BaseTestStruct
  415. C string
  416. }
  417. const SCRIPT = `
  418. var m = {
  419. A: 1,
  420. B: 2,
  421. C: "testC"
  422. }
  423. m;
  424. `
  425. vm := New()
  426. v, err := vm.RunString(SCRIPT)
  427. if err != nil {
  428. t.Fatal(err)
  429. }
  430. test := &TestStruct{}
  431. err = vm.ExportTo(v, test)
  432. if err != nil {
  433. t.Fatal(err)
  434. }
  435. if test.A != 1 {
  436. t.Fatalf("Unexpected value: '%d'", test.A)
  437. }
  438. if test.B != 2 {
  439. t.Fatalf("Unexpected value: '%d'", test.B)
  440. }
  441. if test.C != "testC" {
  442. t.Fatalf("Unexpected value: '%s'", test.C)
  443. }
  444. }
  445. func TestRuntime_ExportToStructWithPtrValues(t *testing.T) {
  446. type BaseTestStruct struct {
  447. A int64
  448. B *int64
  449. }
  450. type TestStruct2 struct {
  451. E string
  452. }
  453. type TestStruct struct {
  454. BaseTestStruct
  455. C *string
  456. D *TestStruct2
  457. }
  458. const SCRIPT = `
  459. var m = {
  460. A: 1,
  461. B: 2,
  462. C: "testC",
  463. D: {
  464. E: "testE",
  465. }
  466. }
  467. m;
  468. `
  469. vm := New()
  470. v, err := vm.RunString(SCRIPT)
  471. if err != nil {
  472. t.Fatal(err)
  473. }
  474. test := &TestStruct{}
  475. err = vm.ExportTo(v, test)
  476. if err != nil {
  477. t.Fatal(err)
  478. }
  479. if test.A != 1 {
  480. t.Fatalf("Unexpected value: '%d'", test.A)
  481. }
  482. if test.B == nil || *test.B != 2 {
  483. t.Fatalf("Unexpected value: '%v'", test.B)
  484. }
  485. if test.C == nil || *test.C != "testC" {
  486. t.Fatalf("Unexpected value: '%v'", test.C)
  487. }
  488. if test.D == nil || test.D.E != "testE" {
  489. t.Fatalf("Unexpected value: '%s'", test.D.E)
  490. }
  491. }
  492. func TestRuntime_ExportToTime(t *testing.T) {
  493. const SCRIPT = `
  494. var dateStr = "2018-08-13T15:02:13+02:00";
  495. var str = "test123";
  496. `
  497. vm := New()
  498. _, err := vm.RunString(SCRIPT)
  499. if err != nil {
  500. t.Fatal(err)
  501. }
  502. var ti time.Time
  503. err = vm.ExportTo(vm.Get("dateStr"), &ti)
  504. if err != nil {
  505. t.Fatal(err)
  506. }
  507. if ti.Format(time.RFC3339) != "2018-08-13T15:02:13+02:00" {
  508. t.Fatalf("Unexpected value: '%s'", ti.Format(time.RFC3339))
  509. }
  510. err = vm.ExportTo(vm.Get("str"), &ti)
  511. if err == nil {
  512. t.Fatal("Expected err to not be nil")
  513. }
  514. var str string
  515. err = vm.ExportTo(vm.Get("dateStr"), &str)
  516. if err != nil {
  517. t.Fatal(err)
  518. }
  519. if str != "2018-08-13T15:02:13+02:00" {
  520. t.Fatalf("Unexpected value: '%s'", str)
  521. }
  522. }
  523. func TestRuntime_ExportToFunc(t *testing.T) {
  524. const SCRIPT = `
  525. function f(param) {
  526. return +param + 2;
  527. }
  528. `
  529. vm := New()
  530. _, err := vm.RunString(SCRIPT)
  531. if err != nil {
  532. t.Fatal(err)
  533. }
  534. var fn func(string) string
  535. vm.ExportTo(vm.Get("f"), &fn)
  536. if res := fn("40"); res != "42" {
  537. t.Fatalf("Unexpected value: %q", res)
  538. }
  539. }
  540. func TestRuntime_ExportToFuncThrow(t *testing.T) {
  541. const SCRIPT = `
  542. function f(param) {
  543. throw new Error("testing");
  544. }
  545. `
  546. vm := New()
  547. _, err := vm.RunString(SCRIPT)
  548. if err != nil {
  549. t.Fatal(err)
  550. }
  551. var fn func(string) (string, error)
  552. err = vm.ExportTo(vm.Get("f"), &fn)
  553. if err != nil {
  554. t.Fatal(err)
  555. }
  556. if _, err := fn("40"); err != nil {
  557. if ex, ok := err.(*Exception); ok {
  558. if msg := ex.Error(); msg != "Error: testing at f (<eval>:3:9(4))" {
  559. t.Fatalf("Msg: %q", msg)
  560. }
  561. } else {
  562. t.Fatalf("Error is not *Exception (%T): %v", err, err)
  563. }
  564. } else {
  565. t.Fatal("Expected error")
  566. }
  567. }
  568. func TestRuntime_ExportToFuncFail(t *testing.T) {
  569. const SCRIPT = `
  570. function f(param) {
  571. return +param + 2;
  572. }
  573. `
  574. type T struct {
  575. Field1 int
  576. }
  577. var fn func(string) (T, error)
  578. vm := New()
  579. _, err := vm.RunString(SCRIPT)
  580. if err != nil {
  581. t.Fatal(err)
  582. }
  583. err = vm.ExportTo(vm.Get("f"), &fn)
  584. if err != nil {
  585. t.Fatal(err)
  586. }
  587. if _, err := fn("40"); err == nil {
  588. t.Fatal("Expected error")
  589. }
  590. }
  591. func TestRuntime_ExportToCallable(t *testing.T) {
  592. const SCRIPT = `
  593. function f(param) {
  594. return +param + 2;
  595. }
  596. `
  597. vm := New()
  598. _, err := vm.RunString(SCRIPT)
  599. if err != nil {
  600. t.Fatal(err)
  601. }
  602. var c Callable
  603. err = vm.ExportTo(vm.Get("f"), &c)
  604. if err != nil {
  605. t.Fatal(err)
  606. }
  607. res, err := c(Undefined(), vm.ToValue("40"))
  608. if err != nil {
  609. t.Fatal(err)
  610. } else if !res.StrictEquals(vm.ToValue(42)) {
  611. t.Fatalf("Unexpected value: %v", res)
  612. }
  613. }
  614. func TestRuntime_ExportToObject(t *testing.T) {
  615. const SCRIPT = `
  616. var o = {"test": 42};
  617. o;
  618. `
  619. vm := New()
  620. _, err := vm.RunString(SCRIPT)
  621. if err != nil {
  622. t.Fatal(err)
  623. }
  624. var o *Object
  625. err = vm.ExportTo(vm.Get("o"), &o)
  626. if err != nil {
  627. t.Fatal(err)
  628. }
  629. if v := o.Get("test"); !v.StrictEquals(vm.ToValue(42)) {
  630. t.Fatalf("Unexpected value: %v", v)
  631. }
  632. }
  633. func TestGoFuncError(t *testing.T) {
  634. const SCRIPT = `
  635. try {
  636. f();
  637. } catch (e) {
  638. if (!(e instanceof GoError)) {
  639. throw(e);
  640. }
  641. if (e.value.Error() !== "Test") {
  642. throw("Unexpected value: " + e.value.Error());
  643. }
  644. }
  645. `
  646. f := func() error {
  647. return errors.New("Test")
  648. }
  649. vm := New()
  650. vm.Set("f", f)
  651. _, err := vm.RunString(SCRIPT)
  652. if err != nil {
  653. t.Fatal(err)
  654. }
  655. }
  656. func TestToValueNil(t *testing.T) {
  657. type T struct{}
  658. var a *T
  659. vm := New()
  660. if v := vm.ToValue(a); !IsNull(v) {
  661. t.Fatalf("Expected null, got: %v", v)
  662. }
  663. }
  664. func TestToValueFloat(t *testing.T) {
  665. vm := New()
  666. vm.Set("f64", float64(123))
  667. vm.Set("f32", float32(321))
  668. v, err := vm.RunString("f64 === 123 && f32 === 321")
  669. if err != nil {
  670. t.Fatal(err)
  671. }
  672. if v.Export().(bool) != true {
  673. t.Fatalf("StrictEquals for golang float failed")
  674. }
  675. }
  676. func TestJSONEscape(t *testing.T) {
  677. const SCRIPT = `
  678. var a = "\\+1";
  679. JSON.stringify(a);
  680. `
  681. testScript1(SCRIPT, asciiString(`"\\+1"`), t)
  682. }
  683. func TestJSONObjectInArray(t *testing.T) {
  684. const SCRIPT = `
  685. var a = "[{\"a\":1},{\"a\":2}]";
  686. JSON.stringify(JSON.parse(a)) == a;
  687. `
  688. testScript1(SCRIPT, valueTrue, t)
  689. }
  690. func TestJSONQuirkyNumbers(t *testing.T) {
  691. const SCRIPT = `
  692. var s;
  693. s = JSON.stringify(NaN);
  694. if (s != "null") {
  695. throw new Error("NaN: " + s);
  696. }
  697. s = JSON.stringify(Infinity);
  698. if (s != "null") {
  699. throw new Error("Infinity: " + s);
  700. }
  701. s = JSON.stringify(-Infinity);
  702. if (s != "null") {
  703. throw new Error("-Infinity: " + s);
  704. }
  705. `
  706. testScript1(SCRIPT, _undefined, t)
  707. }
  708. func TestJSONNil(t *testing.T) {
  709. const SCRIPT = `
  710. JSON.stringify(i);
  711. `
  712. vm := New()
  713. var i interface{}
  714. vm.Set("i", i)
  715. ret, err := vm.RunString(SCRIPT)
  716. if err != nil {
  717. t.Fatal(err)
  718. }
  719. if ret.String() != "null" {
  720. t.Fatalf("Expected 'null', got: %v", ret)
  721. }
  722. }
  723. type customJsonEncodable struct{}
  724. func (*customJsonEncodable) JsonEncodable() interface{} {
  725. return "Test"
  726. }
  727. func TestJsonEncodable(t *testing.T) {
  728. var s customJsonEncodable
  729. vm := New()
  730. vm.Set("s", &s)
  731. ret, err := vm.RunString("JSON.stringify(s)")
  732. if err != nil {
  733. t.Fatal(err)
  734. }
  735. if !ret.StrictEquals(vm.ToValue("\"Test\"")) {
  736. t.Fatalf("Expected \"Test\", got: %v", ret)
  737. }
  738. }
  739. func TestSortComparatorReturnValues(t *testing.T) {
  740. const SCRIPT = `
  741. var a = [];
  742. for (var i = 0; i < 12; i++) {
  743. a[i] = i;
  744. }
  745. a.sort(function(x, y) { return y - x });
  746. for (var i = 0; i < 12; i++) {
  747. if (a[i] !== 11-i) {
  748. throw new Error("Value at index " + i + " is incorrect: " + a[i]);
  749. }
  750. }
  751. `
  752. testScript1(SCRIPT, _undefined, t)
  753. }
  754. func TestNilApplyArg(t *testing.T) {
  755. const SCRIPT = `
  756. (function x(a, b) {
  757. return a === undefined && b === 1;
  758. }).apply(this, [,1])
  759. `
  760. testScript1(SCRIPT, valueTrue, t)
  761. }
  762. func TestNilCallArg(t *testing.T) {
  763. const SCRIPT = `
  764. "use strict";
  765. function f(a) {
  766. return this === undefined && a === undefined;
  767. }
  768. `
  769. vm := New()
  770. prg := MustCompile("test.js", SCRIPT, false)
  771. vm.RunProgram(prg)
  772. if f, ok := AssertFunction(vm.Get("f")); ok {
  773. v, err := f(nil, nil)
  774. if err != nil {
  775. t.Fatal(err)
  776. }
  777. if !v.StrictEquals(valueTrue) {
  778. t.Fatalf("Unexpected result: %v", v)
  779. }
  780. }
  781. }
  782. func TestNullCallArg(t *testing.T) {
  783. const SCRIPT = `
  784. f(null);
  785. `
  786. vm := New()
  787. prg := MustCompile("test.js", SCRIPT, false)
  788. vm.Set("f", func(x *int) bool {
  789. return x == nil
  790. })
  791. v, err := vm.RunProgram(prg)
  792. if err != nil {
  793. t.Fatal(err)
  794. }
  795. if !v.StrictEquals(valueTrue) {
  796. t.Fatalf("Unexpected result: %v", v)
  797. }
  798. }
  799. func TestObjectKeys(t *testing.T) {
  800. const SCRIPT = `
  801. var o = { a: 1, b: 2, c: 3, d: 4 };
  802. o;
  803. `
  804. vm := New()
  805. prg := MustCompile("test.js", SCRIPT, false)
  806. res, err := vm.RunProgram(prg)
  807. if err != nil {
  808. t.Fatal(err)
  809. }
  810. if o, ok := res.(*Object); ok {
  811. keys := o.Keys()
  812. if !reflect.DeepEqual(keys, []string{"a", "b", "c", "d"}) {
  813. t.Fatalf("Unexpected keys: %v", keys)
  814. }
  815. }
  816. }
  817. func TestReflectCallExtraArgs(t *testing.T) {
  818. const SCRIPT = `
  819. f(41, "extra")
  820. `
  821. f := func(x int) int {
  822. return x + 1
  823. }
  824. vm := New()
  825. vm.Set("f", f)
  826. prg := MustCompile("test.js", SCRIPT, false)
  827. res, err := vm.RunProgram(prg)
  828. if err != nil {
  829. t.Fatal(err)
  830. }
  831. if !res.StrictEquals(intToValue(42)) {
  832. t.Fatalf("Unexpected result: %v", res)
  833. }
  834. }
  835. func TestReflectCallNotEnoughArgs(t *testing.T) {
  836. const SCRIPT = `
  837. f(42)
  838. `
  839. vm := New()
  840. f := func(x, y int, z *int, s string) (int, error) {
  841. if z != nil {
  842. return 0, fmt.Errorf("z is not nil")
  843. }
  844. if s != "" {
  845. return 0, fmt.Errorf("s is not \"\"")
  846. }
  847. return x + y, nil
  848. }
  849. vm.Set("f", f)
  850. prg := MustCompile("test.js", SCRIPT, false)
  851. res, err := vm.RunProgram(prg)
  852. if err != nil {
  853. t.Fatal(err)
  854. }
  855. if !res.StrictEquals(intToValue(42)) {
  856. t.Fatalf("Unexpected result: %v", res)
  857. }
  858. }
  859. func TestReflectCallVariadic(t *testing.T) {
  860. const SCRIPT = `
  861. var r = f("Hello %s, %d", "test", 42);
  862. if (r !== "Hello test, 42") {
  863. throw new Error("test 1 has failed: " + r);
  864. }
  865. r = f("Hello %s, %d", ["test", 42]);
  866. if (r !== "Hello test, 42") {
  867. throw new Error("test 2 has failed: " + r);
  868. }
  869. r = f("Hello %s, %s", "test");
  870. if (r !== "Hello test, %!s(MISSING)") {
  871. throw new Error("test 3 has failed: " + r);
  872. }
  873. r = f();
  874. if (r !== "") {
  875. throw new Error("test 4 has failed: " + r);
  876. }
  877. `
  878. vm := New()
  879. vm.Set("f", fmt.Sprintf)
  880. prg := MustCompile("test.js", SCRIPT, false)
  881. _, err := vm.RunProgram(prg)
  882. if err != nil {
  883. t.Fatal(err)
  884. }
  885. }
  886. func TestReflectNullValueArgument(t *testing.T) {
  887. rt := New()
  888. rt.Set("fn", func(v Value) {
  889. if v == nil {
  890. t.Error("null becomes nil")
  891. }
  892. if !IsNull(v) {
  893. t.Error("null is not null")
  894. }
  895. })
  896. rt.RunString(`fn(null);`)
  897. }
  898. type testNativeConstructHelper struct {
  899. rt *Runtime
  900. base int64
  901. // any other state
  902. }
  903. func (t *testNativeConstructHelper) calc(call FunctionCall) Value {
  904. return t.rt.ToValue(t.base + call.Argument(0).ToInteger())
  905. }
  906. func TestNativeConstruct(t *testing.T) {
  907. const SCRIPT = `
  908. var f = new F(40);
  909. f instanceof F && f.method() === 42 && f.calc(2) === 42;
  910. `
  911. rt := New()
  912. method := func(call FunctionCall) Value {
  913. return rt.ToValue(42)
  914. }
  915. rt.Set("F", func(call ConstructorCall) *Object { // constructor signature (as opposed to 'func(FunctionCall) Value')
  916. h := &testNativeConstructHelper{
  917. rt: rt,
  918. base: call.Argument(0).ToInteger(),
  919. }
  920. call.This.Set("method", method)
  921. call.This.Set("calc", h.calc)
  922. return nil // or any other *Object which will be used instead of call.This
  923. })
  924. prg := MustCompile("test.js", SCRIPT, false)
  925. res, err := rt.RunProgram(prg)
  926. if err != nil {
  927. t.Fatal(err)
  928. }
  929. if !res.StrictEquals(valueTrue) {
  930. t.Fatalf("Unexpected result: %v", res)
  931. }
  932. if fn, ok := AssertFunction(rt.Get("F")); ok {
  933. v, err := fn(nil, rt.ToValue(42))
  934. if err != nil {
  935. t.Fatal(err)
  936. }
  937. if o, ok := v.(*Object); ok {
  938. if o.Get("method") == nil {
  939. t.Fatal("No method")
  940. }
  941. } else {
  942. t.Fatal("Not an object")
  943. }
  944. } else {
  945. t.Fatal("Not a function")
  946. }
  947. resp := &testNativeConstructHelper{}
  948. value := rt.ToValue(resp)
  949. if value.Export() != resp {
  950. t.Fatal("no")
  951. }
  952. }
  953. func TestCreateObject(t *testing.T) {
  954. const SCRIPT = `
  955. inst instanceof C;
  956. `
  957. r := New()
  958. c := r.ToValue(func(call ConstructorCall) *Object {
  959. return nil
  960. })
  961. proto := c.(*Object).Get("prototype").(*Object)
  962. inst := r.CreateObject(proto)
  963. r.Set("C", c)
  964. r.Set("inst", inst)
  965. prg := MustCompile("test.js", SCRIPT, false)
  966. res, err := r.RunProgram(prg)
  967. if err != nil {
  968. t.Fatal(err)
  969. }
  970. if !res.StrictEquals(valueTrue) {
  971. t.Fatalf("Unexpected result: %v", res)
  972. }
  973. }
  974. func TestInterruptInWrappedFunction(t *testing.T) {
  975. rt := New()
  976. v, err := rt.RunString(`
  977. var fn = function() {
  978. while (true) {}
  979. };
  980. fn;
  981. `)
  982. if err != nil {
  983. t.Fatal(err)
  984. }
  985. fn, ok := AssertFunction(v)
  986. if !ok {
  987. t.Fatal("Not a function")
  988. }
  989. go func() {
  990. <-time.After(10 * time.Millisecond)
  991. rt.Interrupt(errors.New("hi"))
  992. }()
  993. v, err = fn(nil)
  994. if err == nil {
  995. t.Fatal("expected error")
  996. }
  997. if _, ok := err.(*InterruptedError); !ok {
  998. t.Fatalf("Wrong error type: %T", err)
  999. }
  1000. }
  1001. func TestNaN(t *testing.T) {
  1002. if !IsNaN(_NaN) {
  1003. t.Fatal("IsNaN() doesn't detect NaN")
  1004. }
  1005. if IsNaN(Undefined()) {
  1006. t.Fatal("IsNaN() says undefined is a NaN")
  1007. }
  1008. if !IsNaN(NaN()) {
  1009. t.Fatal("NaN() doesn't return NaN")
  1010. }
  1011. }
  1012. func TestInf(t *testing.T) {
  1013. if !IsInfinity(_positiveInf) {
  1014. t.Fatal("IsInfinity() doesn't detect +Inf")
  1015. }
  1016. if !IsInfinity(_negativeInf) {
  1017. t.Fatal("IsInfinity() doesn't detect -Inf")
  1018. }
  1019. if IsInfinity(Undefined()) {
  1020. t.Fatal("IsInfinity() says undefined is a Infinity")
  1021. }
  1022. if !IsInfinity(PositiveInf()) {
  1023. t.Fatal("PositiveInfinity() doesn't return Inf")
  1024. }
  1025. if !IsInfinity(NegativeInf()) {
  1026. t.Fatal("NegativeInfinity() doesn't return Inf")
  1027. }
  1028. }
  1029. /*
  1030. func TestArrayConcatSparse(t *testing.T) {
  1031. function foo(a,b,c)
  1032. {
  1033. arguments[0] = 1; arguments[1] = 'str'; arguments[2] = 2.1;
  1034. if(1 === a && 'str' === b && 2.1 === c)
  1035. return true;
  1036. }
  1037. const SCRIPT = `
  1038. var a1 = [];
  1039. var a2 = [];
  1040. a1[500000] = 1;
  1041. a2[1000000] = 2;
  1042. var a3 = a1.concat(a2);
  1043. a3.length === 1500002 && a3[500000] === 1 && a3[1500001] == 2;
  1044. `
  1045. testScript1(SCRIPT, valueTrue, t)
  1046. }
  1047. */
  1048. func BenchmarkCallReflect(b *testing.B) {
  1049. vm := New()
  1050. vm.Set("f", func(v Value) {
  1051. })
  1052. prg := MustCompile("test.js", "f(null)", true)
  1053. b.ResetTimer()
  1054. for i := 0; i < b.N; i++ {
  1055. vm.RunProgram(prg)
  1056. }
  1057. }
  1058. func BenchmarkCallNative(b *testing.B) {
  1059. vm := New()
  1060. vm.Set("f", func(call FunctionCall) (ret Value) {
  1061. return
  1062. })
  1063. prg := MustCompile("test.js", "f(null)", true)
  1064. b.ResetTimer()
  1065. for i := 0; i < b.N; i++ {
  1066. vm.RunProgram(prg)
  1067. }
  1068. }