object_goreflect_test.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  1. package goja
  2. import (
  3. "errors"
  4. "fmt"
  5. "math"
  6. "reflect"
  7. "strings"
  8. "testing"
  9. "time"
  10. )
  11. func TestGoReflectGet(t *testing.T) {
  12. const SCRIPT = `
  13. o.X + o.Y;
  14. `
  15. type O struct {
  16. X int
  17. Y string
  18. }
  19. r := New()
  20. o := O{X: 4, Y: "2"}
  21. r.Set("o", o)
  22. v, err := r.RunString(SCRIPT)
  23. if err != nil {
  24. t.Fatal(err)
  25. }
  26. if s, ok := v.(String); ok {
  27. if s.String() != "42" {
  28. t.Fatalf("Unexpected string: %s", s)
  29. }
  30. } else {
  31. t.Fatalf("Unexpected type: %s", v)
  32. }
  33. }
  34. func TestGoReflectSet(t *testing.T) {
  35. const SCRIPT = `
  36. o.X++;
  37. o.Y += "P";
  38. `
  39. type O struct {
  40. X int
  41. Y string
  42. }
  43. r := New()
  44. o := O{X: 4, Y: "2"}
  45. r.Set("o", &o)
  46. _, err := r.RunString(SCRIPT)
  47. if err != nil {
  48. t.Fatal(err)
  49. }
  50. if o.X != 5 {
  51. t.Fatalf("Unexpected X: %d", o.X)
  52. }
  53. if o.Y != "2P" {
  54. t.Fatalf("Unexpected Y: %s", o.Y)
  55. }
  56. r.Set("o", o)
  57. _, err = r.RunString(SCRIPT)
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. if res, ok := r.Get("o").Export().(O); ok {
  62. if res.X != 6 {
  63. t.Fatalf("Unexpected res.X: %d", res.X)
  64. }
  65. if res.Y != "2PP" {
  66. t.Fatalf("Unexpected res.Y: %s", res.Y)
  67. }
  68. }
  69. }
  70. func TestGoReflectEnumerate(t *testing.T) {
  71. const SCRIPT = `
  72. var hasX = false;
  73. var hasY = false;
  74. for (var key in o) {
  75. switch (key) {
  76. case "X":
  77. if (hasX) {
  78. throw "Already have X";
  79. }
  80. hasX = true;
  81. break;
  82. case "Y":
  83. if (hasY) {
  84. throw "Already have Y";
  85. }
  86. hasY = true;
  87. break;
  88. default:
  89. throw "Unexpected property: " + key;
  90. }
  91. }
  92. hasX && hasY;
  93. `
  94. type S struct {
  95. X, Y int
  96. }
  97. r := New()
  98. r.Set("o", S{X: 40, Y: 2})
  99. v, err := r.RunString(SCRIPT)
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. if !v.StrictEquals(valueTrue) {
  104. t.Fatalf("Expected true, got %v", v)
  105. }
  106. }
  107. func TestGoReflectCustomIntUnbox(t *testing.T) {
  108. const SCRIPT = `
  109. i + 2;
  110. `
  111. type CustomInt int
  112. var i CustomInt = 40
  113. r := New()
  114. r.Set("i", i)
  115. v, err := r.RunString(SCRIPT)
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. if !v.StrictEquals(intToValue(42)) {
  120. t.Fatalf("Expected int 42, got %v", v)
  121. }
  122. }
  123. func TestGoReflectPreserveCustomType(t *testing.T) {
  124. const SCRIPT = `
  125. i;
  126. `
  127. type CustomInt int
  128. var i CustomInt = 42
  129. r := New()
  130. r.Set("i", i)
  131. v, err := r.RunString(SCRIPT)
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. ve := v.Export()
  136. if ii, ok := ve.(CustomInt); ok {
  137. if ii != i {
  138. t.Fatalf("Wrong value: %v", ii)
  139. }
  140. } else {
  141. t.Fatalf("Wrong type: %v", ve)
  142. }
  143. }
  144. func TestGoReflectCustomIntValueOf(t *testing.T) {
  145. const SCRIPT = `
  146. if (i instanceof Number) {
  147. i.valueOf();
  148. } else {
  149. throw new Error("Value is not a number");
  150. }
  151. `
  152. type CustomInt int
  153. var i CustomInt = 42
  154. r := New()
  155. r.Set("i", i)
  156. v, err := r.RunString(SCRIPT)
  157. if err != nil {
  158. t.Fatal(err)
  159. }
  160. if !v.StrictEquals(intToValue(42)) {
  161. t.Fatalf("Expected int 42, got %v", v)
  162. }
  163. }
  164. func TestGoReflectEqual(t *testing.T) {
  165. const SCRIPT = `
  166. x === y;
  167. `
  168. type CustomInt int
  169. var x CustomInt = 42
  170. var y CustomInt = 42
  171. r := New()
  172. r.Set("x", x)
  173. r.Set("y", y)
  174. v, err := r.RunString(SCRIPT)
  175. if err != nil {
  176. t.Fatal(err)
  177. }
  178. if !v.StrictEquals(valueTrue) {
  179. t.Fatalf("Expected true, got %v", v)
  180. }
  181. }
  182. type testGoReflectMethod_O struct {
  183. field string
  184. Test string
  185. }
  186. func (o testGoReflectMethod_O) Method(s string) string {
  187. return o.field + s
  188. }
  189. func TestGoReflectMethod(t *testing.T) {
  190. const SCRIPT = `
  191. o.Method(" 123")
  192. `
  193. o := testGoReflectMethod_O{
  194. field: "test",
  195. }
  196. r := New()
  197. r.Set("o", &o)
  198. v, err := r.RunString(SCRIPT)
  199. if err != nil {
  200. t.Fatal(err)
  201. }
  202. if !v.StrictEquals(asciiString("test 123")) {
  203. t.Fatalf("Expected 'test 123', got %v", v)
  204. }
  205. }
  206. func (o *testGoReflectMethod_O) Set(s string) {
  207. o.field = s
  208. }
  209. func (o *testGoReflectMethod_O) Get() string {
  210. return o.field
  211. }
  212. func TestGoReflectMethodPtr(t *testing.T) {
  213. const SCRIPT = `
  214. o.Set("42")
  215. o.Get()
  216. `
  217. o := testGoReflectMethod_O{
  218. field: "test",
  219. }
  220. r := New()
  221. r.Set("o", &o)
  222. v, err := r.RunString(SCRIPT)
  223. if err != nil {
  224. t.Fatal(err)
  225. }
  226. if !v.StrictEquals(asciiString("42")) {
  227. t.Fatalf("Expected '42', got %v", v)
  228. }
  229. }
  230. func (b *testBoolS) Method() bool {
  231. return bool(*b)
  232. }
  233. func TestGoReflectPtrMethodOnNonPtrValue(t *testing.T) {
  234. var o testGoReflectMethod_O
  235. o.Get()
  236. vm := New()
  237. vm.Set("o", o)
  238. _, err := vm.RunString(`o.Get()`)
  239. if err != nil {
  240. t.Fatal(err)
  241. }
  242. _, err = vm.RunString(`o.Method()`)
  243. if err != nil {
  244. t.Fatal(err)
  245. }
  246. var b testBoolS
  247. vm.Set("b", b)
  248. _, err = vm.RunString(`b.Method()`)
  249. if err != nil {
  250. t.Fatal(err)
  251. }
  252. }
  253. func TestGoReflectStructField(t *testing.T) {
  254. type S struct {
  255. F testGoReflectMethod_O
  256. B testBoolS
  257. }
  258. var s S
  259. vm := New()
  260. vm.Set("s", &s)
  261. const SCRIPT = `
  262. s.F.Set("Test");
  263. assert.sameValue(s.F.Method(""), "Test", "1");
  264. s.B = true;
  265. assert.sameValue(s.B.Method(), true, "2");
  266. assert.sameValue(s.B.toString(), "B", "3");
  267. `
  268. vm.testScriptWithTestLib(SCRIPT, _undefined, t)
  269. }
  270. func TestGoReflectProp(t *testing.T) {
  271. const SCRIPT = `
  272. var d1 = Object.getOwnPropertyDescriptor(o, "Get");
  273. var d2 = Object.getOwnPropertyDescriptor(o, "Test");
  274. !d1.writable && !d1.configurable && d2.writable && !d2.configurable;
  275. `
  276. o := testGoReflectMethod_O{
  277. field: "test",
  278. }
  279. r := New()
  280. r.Set("o", &o)
  281. v, err := r.RunString(SCRIPT)
  282. if err != nil {
  283. t.Fatal(err)
  284. }
  285. if !v.StrictEquals(valueTrue) {
  286. t.Fatalf("Expected true, got %v", v)
  287. }
  288. }
  289. func TestGoReflectRedefineFieldSuccess(t *testing.T) {
  290. const SCRIPT = `
  291. Object.defineProperty(o, "Test", {value: "AAA"}) === o;
  292. `
  293. o := testGoReflectMethod_O{}
  294. r := New()
  295. r.Set("o", &o)
  296. v, err := r.RunString(SCRIPT)
  297. if err != nil {
  298. t.Fatal(err)
  299. }
  300. if !v.StrictEquals(valueTrue) {
  301. t.Fatalf("Expected true, got %v", v)
  302. }
  303. if o.Test != "AAA" {
  304. t.Fatalf("Expected 'AAA', got '%s'", o.Test)
  305. }
  306. }
  307. func TestGoReflectRedefineFieldNonWritable(t *testing.T) {
  308. const SCRIPT = `
  309. var thrown = false;
  310. try {
  311. Object.defineProperty(o, "Test", {value: "AAA", writable: false});
  312. } catch (e) {
  313. if (e instanceof TypeError) {
  314. thrown = true;
  315. } else {
  316. throw e;
  317. }
  318. }
  319. thrown;
  320. `
  321. o := testGoReflectMethod_O{Test: "Test"}
  322. r := New()
  323. r.Set("o", &o)
  324. v, err := r.RunString(SCRIPT)
  325. if err != nil {
  326. t.Fatal(err)
  327. }
  328. if !v.StrictEquals(valueTrue) {
  329. t.Fatalf("Expected true, got %v", v)
  330. }
  331. if o.Test != "Test" {
  332. t.Fatalf("Expected 'Test', got: '%s'", o.Test)
  333. }
  334. }
  335. func TestGoReflectRedefineFieldConfigurable(t *testing.T) {
  336. const SCRIPT = `
  337. var thrown = false;
  338. try {
  339. Object.defineProperty(o, "Test", {value: "AAA", configurable: true});
  340. } catch (e) {
  341. if (e instanceof TypeError) {
  342. thrown = true;
  343. } else {
  344. throw e;
  345. }
  346. }
  347. thrown;
  348. `
  349. o := testGoReflectMethod_O{Test: "Test"}
  350. r := New()
  351. r.Set("o", &o)
  352. v, err := r.RunString(SCRIPT)
  353. if err != nil {
  354. t.Fatal(err)
  355. }
  356. if !v.StrictEquals(valueTrue) {
  357. t.Fatalf("Expected true, got %v", v)
  358. }
  359. if o.Test != "Test" {
  360. t.Fatalf("Expected 'Test', got: '%s'", o.Test)
  361. }
  362. }
  363. func TestGoReflectRedefineMethod(t *testing.T) {
  364. const SCRIPT = `
  365. var thrown = false;
  366. try {
  367. Object.defineProperty(o, "Method", {value: "AAA", configurable: true});
  368. } catch (e) {
  369. if (e instanceof TypeError) {
  370. thrown = true;
  371. } else {
  372. throw e;
  373. }
  374. }
  375. thrown;
  376. `
  377. o := testGoReflectMethod_O{Test: "Test"}
  378. r := New()
  379. r.Set("o", &o)
  380. v, err := r.RunString(SCRIPT)
  381. if err != nil {
  382. t.Fatal(err)
  383. }
  384. if !v.StrictEquals(valueTrue) {
  385. t.Fatalf("Expected true, got %v", v)
  386. }
  387. }
  388. func TestGoReflectEmbeddedStruct(t *testing.T) {
  389. const SCRIPT = `
  390. if (o.ParentField2 !== "ParentField2") {
  391. throw new Error("ParentField2 = " + o.ParentField2);
  392. }
  393. if (o.Parent.ParentField2 !== 2) {
  394. throw new Error("o.Parent.ParentField2 = " + o.Parent.ParentField2);
  395. }
  396. if (o.ParentField1 !== 1) {
  397. throw new Error("o.ParentField1 = " + o.ParentField1);
  398. }
  399. if (o.ChildField !== 3) {
  400. throw new Error("o.ChildField = " + o.ChildField);
  401. }
  402. var keys = {};
  403. for (var k in o) {
  404. if (keys[k]) {
  405. throw new Error("Duplicate key: " + k);
  406. }
  407. keys[k] = true;
  408. }
  409. var expectedKeys = ["ParentField2", "ParentField1", "Parent", "ChildField"];
  410. for (var i in expectedKeys) {
  411. if (!keys[expectedKeys[i]]) {
  412. throw new Error("Missing key in enumeration: " + expectedKeys[i]);
  413. }
  414. delete keys[expectedKeys[i]];
  415. }
  416. var remainingKeys = Object.keys(keys);
  417. if (remainingKeys.length > 0) {
  418. throw new Error("Unexpected keys: " + remainingKeys);
  419. }
  420. o.ParentField2 = "ParentField22";
  421. o.Parent.ParentField2 = 22;
  422. o.ParentField1 = 11;
  423. o.ChildField = 33;
  424. `
  425. type Parent struct {
  426. ParentField1 int
  427. ParentField2 int
  428. }
  429. type Child struct {
  430. ParentField2 string
  431. Parent
  432. ChildField int
  433. }
  434. vm := New()
  435. o := Child{
  436. Parent: Parent{
  437. ParentField1: 1,
  438. ParentField2: 2,
  439. },
  440. ParentField2: "ParentField2",
  441. ChildField: 3,
  442. }
  443. vm.Set("o", &o)
  444. _, err := vm.RunString(SCRIPT)
  445. if err != nil {
  446. t.Fatal(err)
  447. }
  448. if o.ParentField2 != "ParentField22" {
  449. t.Fatalf("ParentField2 = %q", o.ParentField2)
  450. }
  451. if o.Parent.ParentField2 != 22 {
  452. t.Fatalf("Parent.ParentField2 = %d", o.Parent.ParentField2)
  453. }
  454. if o.ParentField1 != 11 {
  455. t.Fatalf("ParentField1 = %d", o.ParentField1)
  456. }
  457. if o.ChildField != 33 {
  458. t.Fatalf("ChildField = %d", o.ChildField)
  459. }
  460. }
  461. type jsonTagNamer struct{}
  462. func (jsonTagNamer) FieldName(_ reflect.Type, field reflect.StructField) string {
  463. if jsonTag := field.Tag.Get("json"); jsonTag != "" {
  464. return jsonTag
  465. }
  466. return field.Name
  467. }
  468. func (jsonTagNamer) MethodName(_ reflect.Type, method reflect.Method) string {
  469. return method.Name
  470. }
  471. func TestGoReflectCustomNaming(t *testing.T) {
  472. type testStructWithJsonTags struct {
  473. A string `json:"b"` // <-- script sees field "A" as property "b"
  474. }
  475. o := &testStructWithJsonTags{"Hello world"}
  476. r := New()
  477. r.SetFieldNameMapper(&jsonTagNamer{})
  478. r.Set("fn", func() *testStructWithJsonTags { return o })
  479. t.Run("get property", func(t *testing.T) {
  480. v, err := r.RunString(`fn().b`)
  481. if err != nil {
  482. t.Fatal(err)
  483. }
  484. if !v.StrictEquals(newStringValue(o.A)) {
  485. t.Fatalf("Expected %q, got %v", o.A, v)
  486. }
  487. })
  488. t.Run("set property", func(t *testing.T) {
  489. _, err := r.RunString(`fn().b = "Hello universe"`)
  490. if err != nil {
  491. t.Fatal(err)
  492. }
  493. if o.A != "Hello universe" {
  494. t.Fatalf("Expected \"Hello universe\", got %q", o.A)
  495. }
  496. })
  497. t.Run("enumerate properties", func(t *testing.T) {
  498. v, err := r.RunString(`Object.keys(fn())`)
  499. if err != nil {
  500. t.Fatal(err)
  501. }
  502. if !reflect.DeepEqual(v.Export(), []interface{}{"b"}) {
  503. t.Fatalf("Expected [\"b\"], got %v", v.Export())
  504. }
  505. })
  506. }
  507. func TestGoReflectCustomObjNaming(t *testing.T) {
  508. type testStructWithJsonTags struct {
  509. A string `json:"b"` // <-- script sees field "A" as property "b"
  510. }
  511. r := New()
  512. r.SetFieldNameMapper(&jsonTagNamer{})
  513. t.Run("Set object in slice", func(t *testing.T) {
  514. testSlice := &[]testStructWithJsonTags{{"Hello world"}}
  515. r.Set("testslice", testSlice)
  516. _, err := r.RunString(`testslice[0] = {b:"setted"}`)
  517. if err != nil {
  518. t.Fatal(err)
  519. }
  520. if (*testSlice)[0].A != "setted" {
  521. t.Fatalf("Expected \"setted\", got %q", (*testSlice)[0])
  522. }
  523. })
  524. t.Run("Set object in map", func(t *testing.T) {
  525. testMap := map[string]testStructWithJsonTags{"key": {"Hello world"}}
  526. r.Set("testmap", testMap)
  527. _, err := r.RunString(`testmap["key"] = {b:"setted"}`)
  528. if err != nil {
  529. t.Fatal(err)
  530. }
  531. if testMap["key"].A != "setted" {
  532. t.Fatalf("Expected \"setted\", got %q", testMap["key"])
  533. }
  534. })
  535. t.Run("Add object to map", func(t *testing.T) {
  536. testMap := map[string]testStructWithJsonTags{}
  537. r.Set("testmap", testMap)
  538. _, err := r.RunString(`testmap["newkey"] = {b:"setted"}`)
  539. if err != nil {
  540. t.Fatal(err)
  541. }
  542. if testMap["newkey"].A != "setted" {
  543. t.Fatalf("Expected \"setted\", got %q", testMap["newkey"])
  544. }
  545. })
  546. }
  547. type fieldNameMapper1 struct{}
  548. func (fieldNameMapper1) FieldName(_ reflect.Type, f reflect.StructField) string {
  549. return strings.ToLower(f.Name)
  550. }
  551. func (fieldNameMapper1) MethodName(_ reflect.Type, m reflect.Method) string {
  552. return m.Name
  553. }
  554. func TestNonStructAnonFields(t *testing.T) {
  555. type Test1 struct {
  556. M bool
  557. }
  558. type test3 []int
  559. type Test4 []int
  560. type Test2 struct {
  561. test3
  562. Test4
  563. *Test1
  564. }
  565. const SCRIPT = `
  566. JSON.stringify(a);
  567. a.m && a.test3 === undefined && a.test4.length === 2
  568. `
  569. vm := New()
  570. vm.SetFieldNameMapper(fieldNameMapper1{})
  571. vm.Set("a", &Test2{Test1: &Test1{M: true}, Test4: []int{1, 2}, test3: nil})
  572. v, err := vm.RunString(SCRIPT)
  573. if err != nil {
  574. t.Fatal(err)
  575. }
  576. if !v.StrictEquals(valueTrue) {
  577. t.Fatalf("Unexepected result: %v", v)
  578. }
  579. }
  580. func TestStructNonAddressable(t *testing.T) {
  581. type S struct {
  582. Field int
  583. }
  584. const SCRIPT = `
  585. "use strict";
  586. if (!Object.getOwnPropertyDescriptor(s, "Field").writable) {
  587. throw new Error("s.Field is non-writable");
  588. }
  589. if (!Object.getOwnPropertyDescriptor(s1, "Field").writable) {
  590. throw new Error("s1.Field is non-writable");
  591. }
  592. s1.Field = 42;
  593. s.Field = 43;
  594. s;
  595. `
  596. var s S
  597. vm := New()
  598. vm.Set("s", s)
  599. vm.Set("s1", &s)
  600. v, err := vm.RunString(SCRIPT)
  601. if err != nil {
  602. t.Fatal(err)
  603. }
  604. exp := v.Export()
  605. if s1, ok := exp.(S); ok {
  606. if s1.Field != 43 {
  607. t.Fatal(s1)
  608. }
  609. } else {
  610. t.Fatalf("Wrong type: %T", exp)
  611. }
  612. if s.Field != 42 {
  613. t.Fatalf("Unexpected s.Field value: %d", s.Field)
  614. }
  615. }
  616. type testFieldMapper struct {
  617. }
  618. func (testFieldMapper) FieldName(_ reflect.Type, f reflect.StructField) string {
  619. if tag := f.Tag.Get("js"); tag != "" {
  620. if tag == "-" {
  621. return ""
  622. }
  623. return tag
  624. }
  625. return f.Name
  626. }
  627. func (testFieldMapper) MethodName(_ reflect.Type, m reflect.Method) string {
  628. return m.Name
  629. }
  630. func TestHidingAnonField(t *testing.T) {
  631. type InnerType struct {
  632. AnotherField string
  633. }
  634. type OuterType struct {
  635. InnerType `js:"-"`
  636. SomeField string
  637. }
  638. const SCRIPT = `
  639. var a = Object.getOwnPropertyNames(o);
  640. if (a.length !== 2) {
  641. throw new Error("unexpected length: " + a.length);
  642. }
  643. if (a.indexOf("SomeField") === -1) {
  644. throw new Error("no SomeField");
  645. }
  646. if (a.indexOf("AnotherField") === -1) {
  647. throw new Error("no SomeField");
  648. }
  649. `
  650. var o OuterType
  651. vm := New()
  652. vm.SetFieldNameMapper(testFieldMapper{})
  653. vm.Set("o", &o)
  654. _, err := vm.RunString(SCRIPT)
  655. if err != nil {
  656. t.Fatal(err)
  657. }
  658. }
  659. func TestFieldOverriding(t *testing.T) {
  660. type InnerType struct {
  661. AnotherField string
  662. AnotherField1 string
  663. }
  664. type OuterType struct {
  665. InnerType `js:"-"`
  666. SomeField string
  667. AnotherField string `js:"-"`
  668. AnotherField1 string
  669. }
  670. const SCRIPT = `
  671. if (o.SomeField !== "SomeField") {
  672. throw new Error("SomeField");
  673. }
  674. if (o.AnotherField !== "AnotherField inner") {
  675. throw new Error("AnotherField");
  676. }
  677. if (o.AnotherField1 !== "AnotherField1 outer") {
  678. throw new Error("AnotherField1");
  679. }
  680. if (o.InnerType) {
  681. throw new Error("InnerType is present");
  682. }
  683. `
  684. o := OuterType{
  685. InnerType: InnerType{
  686. AnotherField: "AnotherField inner",
  687. AnotherField1: "AnotherField1 inner",
  688. },
  689. SomeField: "SomeField",
  690. AnotherField: "AnotherField outer",
  691. AnotherField1: "AnotherField1 outer",
  692. }
  693. vm := New()
  694. vm.SetFieldNameMapper(testFieldMapper{})
  695. vm.Set("o", &o)
  696. _, err := vm.RunString(SCRIPT)
  697. if err != nil {
  698. t.Fatal(err)
  699. }
  700. }
  701. func TestDefinePropertyUnexportedJsName(t *testing.T) {
  702. type T struct {
  703. Field int
  704. unexported int
  705. }
  706. vm := New()
  707. vm.SetFieldNameMapper(fieldNameMapper1{})
  708. vm.Set("f", &T{unexported: 0})
  709. _, err := vm.RunString(`
  710. "use strict";
  711. Object.defineProperty(f, "field", {value: 42});
  712. if (f.field !== 42) {
  713. throw new Error("Unexpected value: " + f.field);
  714. }
  715. if (f.hasOwnProperty("unexported")) {
  716. throw new Error("hasOwnProperty('unexported') is true");
  717. }
  718. var thrown;
  719. try {
  720. Object.defineProperty(f, "unexported", {value: 1});
  721. } catch (e) {
  722. thrown = e;
  723. }
  724. if (!(thrown instanceof TypeError)) {
  725. throw new Error("Unexpected error: ", thrown);
  726. }
  727. `)
  728. if err != nil {
  729. t.Fatal(err)
  730. }
  731. }
  732. type fieldNameMapperToLower struct{}
  733. func (fieldNameMapperToLower) FieldName(_ reflect.Type, f reflect.StructField) string {
  734. return strings.ToLower(f.Name)
  735. }
  736. func (fieldNameMapperToLower) MethodName(_ reflect.Type, m reflect.Method) string {
  737. return strings.ToLower(m.Name)
  738. }
  739. func TestHasOwnPropertyUnexportedJsName(t *testing.T) {
  740. vm := New()
  741. vm.SetFieldNameMapper(fieldNameMapperToLower{})
  742. vm.Set("f", &testGoReflectMethod_O{})
  743. _, err := vm.RunString(`
  744. "use strict";
  745. if (!f.hasOwnProperty("test")) {
  746. throw new Error("hasOwnProperty('test') returned false");
  747. }
  748. if (!f.hasOwnProperty("method")) {
  749. throw new Error("hasOwnProperty('method') returned false");
  750. }
  751. `)
  752. if err != nil {
  753. t.Fatal(err)
  754. }
  755. }
  756. func BenchmarkGoReflectGet(b *testing.B) {
  757. type parent struct {
  758. field, Test1, Test2, Test3, Test4, Test5, Test string
  759. }
  760. type child struct {
  761. parent
  762. Test6 string
  763. }
  764. b.StopTimer()
  765. vm := New()
  766. b.StartTimer()
  767. for i := 0; i < b.N; i++ {
  768. v := vm.ToValue(child{parent: parent{Test: "Test", field: ""}}).(*Object)
  769. v.Get("Test")
  770. }
  771. }
  772. func TestNestedStructSet(t *testing.T) {
  773. type B struct {
  774. Field int
  775. }
  776. type A struct {
  777. B B
  778. }
  779. const SCRIPT = `
  780. 'use strict';
  781. a.B.Field++;
  782. if (a1.B.Field != 1) {
  783. throw new Error("a1.B.Field = " + a1.B.Field);
  784. }
  785. var d = Object.getOwnPropertyDescriptor(a1.B, "Field");
  786. if (!d.writable) {
  787. throw new Error("a1.B is not writable");
  788. }
  789. a1.B.Field = 42;
  790. a1;
  791. `
  792. a := A{
  793. B: B{
  794. Field: 1,
  795. },
  796. }
  797. vm := New()
  798. vm.Set("a", &a)
  799. vm.Set("a1", a)
  800. v, err := vm.RunString(SCRIPT)
  801. if err != nil {
  802. t.Fatal(err)
  803. }
  804. exp := v.Export()
  805. if v, ok := exp.(A); ok {
  806. if v.B.Field != 42 {
  807. t.Fatal(v)
  808. }
  809. } else {
  810. t.Fatalf("Wrong type: %T", exp)
  811. }
  812. if v := a.B.Field; v != 2 {
  813. t.Fatalf("Unexpected a.B.Field: %d", v)
  814. }
  815. }
  816. func TestStructNonAddressableAnonStruct(t *testing.T) {
  817. type C struct {
  818. Z int64
  819. X string
  820. }
  821. type B struct {
  822. C
  823. Y string
  824. }
  825. type A struct {
  826. B B
  827. }
  828. a := A{
  829. B: B{
  830. C: C{
  831. Z: 1,
  832. X: "X2",
  833. },
  834. Y: "Y3",
  835. },
  836. }
  837. const SCRIPT = `
  838. "use strict";
  839. var s = JSON.stringify(a);
  840. s;
  841. `
  842. vm := New()
  843. vm.Set("a", &a)
  844. v, err := vm.RunString(SCRIPT)
  845. if err != nil {
  846. t.Fatal(err)
  847. }
  848. expected := `{"B":{"C":{"Z":1,"X":"X2"},"Z":1,"X":"X2","Y":"Y3"}}`
  849. if expected != v.String() {
  850. t.Fatalf("Expected '%s', got '%s'", expected, v.String())
  851. }
  852. }
  853. func TestTagFieldNameMapperInvalidId(t *testing.T) {
  854. vm := New()
  855. vm.SetFieldNameMapper(TagFieldNameMapper("json", true))
  856. type S struct {
  857. Field int `json:"-"`
  858. }
  859. vm.Set("s", S{Field: 42})
  860. res, err := vm.RunString(`s.hasOwnProperty("field") || s.hasOwnProperty("Field")`)
  861. if err != nil {
  862. t.Fatal(err)
  863. }
  864. if res != valueFalse {
  865. t.Fatalf("Unexpected result: %v", res)
  866. }
  867. }
  868. func TestPrimitivePtr(t *testing.T) {
  869. vm := New()
  870. s := "test"
  871. vm.Set("s", &s)
  872. res, err := vm.RunString(`s instanceof String && s == "test"`) // note non-strict equality
  873. if err != nil {
  874. t.Fatal(err)
  875. }
  876. if v := res.ToBoolean(); !v {
  877. t.Fatalf("value: %#v", res)
  878. }
  879. s = "test1"
  880. res, err = vm.RunString(`s == "test1"`)
  881. if err != nil {
  882. t.Fatal(err)
  883. }
  884. if v := res.ToBoolean(); !v {
  885. t.Fatalf("value: %#v", res)
  886. }
  887. }
  888. func TestStringer(t *testing.T) {
  889. vm := New()
  890. vm.Set("e", errors.New("test"))
  891. res, err := vm.RunString("e.toString()")
  892. if err != nil {
  893. t.Fatal(err)
  894. }
  895. if v := res.Export(); v != "test" {
  896. t.Fatalf("v: %v", v)
  897. }
  898. }
  899. func ExampleTagFieldNameMapper() {
  900. vm := New()
  901. vm.SetFieldNameMapper(TagFieldNameMapper("json", true))
  902. type S struct {
  903. Field int `json:"field"`
  904. }
  905. vm.Set("s", S{Field: 42})
  906. res, _ := vm.RunString(`s.field`)
  907. fmt.Println(res.Export())
  908. // Output: 42
  909. }
  910. func ExampleUncapFieldNameMapper() {
  911. vm := New()
  912. s := testGoReflectMethod_O{
  913. Test: "passed",
  914. }
  915. vm.SetFieldNameMapper(UncapFieldNameMapper())
  916. vm.Set("s", s)
  917. res, _ := vm.RunString(`s.test + " and " + s.method("passed too")`)
  918. fmt.Println(res.Export())
  919. // Output: passed and passed too
  920. }
  921. func TestGoReflectWithProto(t *testing.T) {
  922. type S struct {
  923. Field int
  924. }
  925. var s S
  926. vm := New()
  927. vm.Set("s", &s)
  928. vm.testScriptWithTestLib(`
  929. (function() {
  930. 'use strict';
  931. var proto = {
  932. Field: "protoField",
  933. test: 42
  934. };
  935. var test1Holder;
  936. Object.defineProperty(proto, "test1", {
  937. set: function(v) {
  938. test1Holder = v;
  939. },
  940. get: function() {
  941. return test1Holder;
  942. }
  943. });
  944. Object.setPrototypeOf(s, proto);
  945. assert.sameValue(s.Field, 0, "s.Field");
  946. s.Field = 2;
  947. assert.sameValue(s.Field, 2, "s.Field");
  948. assert.sameValue(s.test, 42, "s.test");
  949. assert.throws(TypeError, function() {
  950. Object.defineProperty(s, "test", {value: 43});
  951. });
  952. test1Holder = 1;
  953. assert.sameValue(s.test1, 1, "s.test1");
  954. s.test1 = 2;
  955. assert.sameValue(test1Holder, 2, "test1Holder");
  956. })();
  957. `, _undefined, t)
  958. }
  959. func TestGoReflectSymbols(t *testing.T) {
  960. type S struct {
  961. Field int
  962. }
  963. var s S
  964. vm := New()
  965. vm.Set("s", &s)
  966. _, err := vm.RunString(`
  967. 'use strict';
  968. var sym = Symbol(66);
  969. s[sym] = "Test";
  970. if (s[sym] !== "Test") {
  971. throw new Error("s[sym]=" + s[sym]);
  972. }
  973. `)
  974. if err != nil {
  975. t.Fatal(err)
  976. }
  977. }
  978. func TestGoReflectSymbolEqualityQuirk(t *testing.T) {
  979. type Field struct {
  980. }
  981. type S struct {
  982. Field *Field
  983. }
  984. var s = S{
  985. Field: &Field{},
  986. }
  987. vm := New()
  988. vm.Set("s", &s)
  989. res, err := vm.RunString(`
  990. var sym = Symbol(66);
  991. var field1 = s.Field;
  992. field1[sym] = true;
  993. var field2 = s.Field;
  994. // Because a wrapper is created every time the property is accessed
  995. // field1 and field2 will be different instances of the wrapper.
  996. // Symbol properties only exist in the wrapper, they cannot be placed into the original Go value,
  997. // hence the following:
  998. field1 === field2 && field1[sym] === true && field2[sym] === undefined;
  999. `)
  1000. if err != nil {
  1001. t.Fatal(err)
  1002. }
  1003. if res != valueTrue {
  1004. t.Fatal(res)
  1005. }
  1006. }
  1007. func TestGoObj__Proto__(t *testing.T) {
  1008. type S struct {
  1009. Field int
  1010. }
  1011. vm := New()
  1012. vm.Set("s", S{})
  1013. vm.Set("m", map[string]interface{}{})
  1014. vm.Set("mr", map[int]string{})
  1015. vm.Set("a", []interface{}{})
  1016. vm.Set("ar", []string{})
  1017. _, err := vm.RunString(`
  1018. function f(s, expectedCtor, prefix) {
  1019. if (s.__proto__ !== expectedCtor.prototype) {
  1020. throw new Error(prefix + ": __proto__: " + s.__proto__);
  1021. }
  1022. s.__proto__ = null;
  1023. if (s.__proto__ !== undefined) { // as there is no longer a prototype, there is no longer the __proto__ property
  1024. throw new Error(prefix + ": __proto__ is not undefined: " + s.__proto__);
  1025. }
  1026. var proto = Object.getPrototypeOf(s);
  1027. if (proto !== null) {
  1028. throw new Error(prefix + ": proto is not null: " + proto);
  1029. }
  1030. }
  1031. f(s, Object, "struct");
  1032. f(m, Object, "simple map");
  1033. f(mr, Object, "reflect map");
  1034. f(a, Array, "slice");
  1035. f(ar, Array, "reflect slice");
  1036. `)
  1037. if err != nil {
  1038. t.Fatal(err)
  1039. }
  1040. }
  1041. func TestGoReflectUnicodeProps(t *testing.T) {
  1042. type S struct {
  1043. Тест string
  1044. }
  1045. vm := New()
  1046. var s S
  1047. vm.Set("s", &s)
  1048. _, err := vm.RunString(`
  1049. if (!s.hasOwnProperty("Тест")) {
  1050. throw new Error("hasOwnProperty");
  1051. }
  1052. `)
  1053. if err != nil {
  1054. t.Fatal(err)
  1055. }
  1056. }
  1057. func TestGoReflectPreserveType(t *testing.T) {
  1058. vm := New()
  1059. var expect = time.Duration(math.MaxInt64)
  1060. vm.Set(`make`, func() time.Duration {
  1061. return expect
  1062. })
  1063. vm.Set(`handle`, func(d time.Duration) {
  1064. if d.String() != expect.String() {
  1065. t.Fatal(`expect`, expect, `, but get`, d)
  1066. }
  1067. })
  1068. _, e := vm.RunString(`
  1069. var d=make()
  1070. handle(d)
  1071. `)
  1072. if e != nil {
  1073. t.Fatal(e)
  1074. }
  1075. }
  1076. func TestGoReflectCopyOnWrite(t *testing.T) {
  1077. type Inner struct {
  1078. Field int
  1079. }
  1080. type S struct {
  1081. I Inner
  1082. }
  1083. var s S
  1084. s.I.Field = 1
  1085. vm := New()
  1086. vm.Set("s", &s)
  1087. _, err := vm.RunString(`
  1088. if (s.I.Field !== 1) {
  1089. throw new Error("s.I.Field: " + s.I.Field);
  1090. }
  1091. let tmp = s.I; // tmp becomes a reference to s.I
  1092. if (tmp.Field !== 1) {
  1093. throw new Error("tmp.Field: " + tmp.Field);
  1094. }
  1095. s.I.Field = 2;
  1096. if (s.I.Field !== 2) {
  1097. throw new Error("s.I.Field (1): " + s.I.Field);
  1098. }
  1099. if (tmp.Field !== 2) {
  1100. throw new Error("tmp.Field (1): " + tmp.Field);
  1101. }
  1102. s.I = {Field: 3}; // at this point tmp is changed to a copy
  1103. if (s.I.Field !== 3) {
  1104. throw new Error("s.I.Field (2): " + s.I.Field);
  1105. }
  1106. if (tmp.Field !== 2) {
  1107. throw new Error("tmp.Field (2): " + tmp.Field);
  1108. }
  1109. `)
  1110. if err != nil {
  1111. t.Fatal(err)
  1112. }
  1113. }
  1114. func TestReflectSetReflectValue(t *testing.T) {
  1115. o := []testGoReflectMethod_O{{}}
  1116. vm := New()
  1117. vm.Set("o", o)
  1118. _, err := vm.RunString(`
  1119. const t = o[0];
  1120. t.Set("a");
  1121. o[0] = {};
  1122. o[0].Set("b");
  1123. if (t.Get() !== "a") {
  1124. throw new Error();
  1125. }
  1126. `)
  1127. if err != nil {
  1128. t.Fatal(err)
  1129. }
  1130. }
  1131. func TestReflectOverwriteReflectMap(t *testing.T) {
  1132. vm := New()
  1133. type S struct {
  1134. M map[int]interface{}
  1135. }
  1136. var s S
  1137. s.M = map[int]interface{}{
  1138. 0: true,
  1139. }
  1140. vm.Set("s", &s)
  1141. _, err := vm.RunString(`
  1142. s.M = {1: false};
  1143. `)
  1144. if err != nil {
  1145. t.Fatal(err)
  1146. }
  1147. if _, exists := s.M[0]; exists {
  1148. t.Fatal(s)
  1149. }
  1150. }
  1151. type testBoolS bool
  1152. func (testBoolS) String() string {
  1153. return "B"
  1154. }
  1155. type testIntS int
  1156. func (testIntS) String() string {
  1157. return "I"
  1158. }
  1159. type testStringS string
  1160. func (testStringS) String() string {
  1161. return "S"
  1162. }
  1163. func TestGoReflectToPrimitive(t *testing.T) {
  1164. vm := New()
  1165. f := func(expr string, expected Value, t *testing.T) {
  1166. v, err := vm.RunString(expr)
  1167. if err != nil {
  1168. t.Fatal(err)
  1169. }
  1170. if IsNaN(expected) {
  1171. if IsNaN(v) {
  1172. return
  1173. }
  1174. } else {
  1175. if v.StrictEquals(expected) {
  1176. return
  1177. }
  1178. }
  1179. t.Fatalf("%s: expected: %v, actual: %v", expr, expected, v)
  1180. }
  1181. t.Run("Not Stringers", func(t *testing.T) {
  1182. type Bool bool
  1183. var b Bool = true
  1184. t.Run("Bool", func(t *testing.T) {
  1185. vm.Set("b", b)
  1186. f("+b", intToValue(1), t)
  1187. f("`${b}`", asciiString("true"), t)
  1188. f("b.toString()", asciiString("true"), t)
  1189. f("b.valueOf()", valueTrue, t)
  1190. })
  1191. t.Run("*Bool", func(t *testing.T) {
  1192. vm.Set("b", &b)
  1193. f("+b", intToValue(1), t)
  1194. f("`${b}`", asciiString("true"), t)
  1195. f("b.toString()", asciiString("true"), t)
  1196. f("b.valueOf()", valueTrue, t)
  1197. })
  1198. type Int int
  1199. var i Int = 1
  1200. t.Run("Int", func(t *testing.T) {
  1201. vm.Set("i", i)
  1202. f("+i", intToValue(1), t)
  1203. f("`${i}`", asciiString("1"), t)
  1204. f("i.toString()", asciiString("1"), t)
  1205. f("i.valueOf()", intToValue(1), t)
  1206. })
  1207. t.Run("*Int", func(t *testing.T) {
  1208. vm.Set("i", &i)
  1209. f("+i", intToValue(1), t)
  1210. f("`${i}`", asciiString("1"), t)
  1211. f("i.toString()", asciiString("1"), t)
  1212. f("i.valueOf()", intToValue(1), t)
  1213. })
  1214. type Uint uint
  1215. var ui Uint = 1
  1216. t.Run("Uint", func(t *testing.T) {
  1217. vm.Set("ui", ui)
  1218. f("+ui", intToValue(1), t)
  1219. f("`${ui}`", asciiString("1"), t)
  1220. f("ui.toString()", asciiString("1"), t)
  1221. f("ui.valueOf()", intToValue(1), t)
  1222. })
  1223. t.Run("*Uint", func(t *testing.T) {
  1224. vm.Set("ui", &i)
  1225. f("+ui", intToValue(1), t)
  1226. f("`${ui}`", asciiString("1"), t)
  1227. f("ui.toString()", asciiString("1"), t)
  1228. f("ui.valueOf()", intToValue(1), t)
  1229. })
  1230. type Float float64
  1231. var fl Float = 1.1
  1232. t.Run("Float", func(t *testing.T) {
  1233. vm.Set("fl", fl)
  1234. f("+fl", floatToValue(1.1), t)
  1235. f("`${fl}`", asciiString("1.1"), t)
  1236. f("fl.toString()", asciiString("1.1"), t)
  1237. f("fl.valueOf()", floatToValue(1.1), t)
  1238. })
  1239. t.Run("*Float", func(t *testing.T) {
  1240. vm.Set("fl", &fl)
  1241. f("+fl", floatToValue(1.1), t)
  1242. f("`${fl}`", asciiString("1.1"), t)
  1243. f("fl.toString()", asciiString("1.1"), t)
  1244. f("fl.valueOf()", floatToValue(1.1), t)
  1245. })
  1246. fl = Float(math.Inf(1))
  1247. t.Run("FloatInf", func(t *testing.T) {
  1248. vm.Set("fl", fl)
  1249. f("+fl", _positiveInf, t)
  1250. f("fl.toString()", asciiString("Infinity"), t)
  1251. })
  1252. type Empty struct{}
  1253. var e Empty
  1254. t.Run("Empty", func(t *testing.T) {
  1255. vm.Set("e", &e)
  1256. f("+e", _NaN, t)
  1257. f("`${e}`", asciiString("[object Object]"), t)
  1258. f("e.toString()", asciiString("[object Object]"), t)
  1259. f("e.valueOf()", vm.ToValue(&e), t)
  1260. })
  1261. })
  1262. t.Run("Stringers", func(t *testing.T) {
  1263. var b testBoolS = true
  1264. t.Run("Bool", func(t *testing.T) {
  1265. vm.Set("b", b)
  1266. f("`${b}`", asciiString("B"), t)
  1267. f("b.toString()", asciiString("B"), t)
  1268. f("b.valueOf()", valueTrue, t)
  1269. f("+b", intToValue(1), t)
  1270. })
  1271. t.Run("*Bool", func(t *testing.T) {
  1272. vm.Set("b", &b)
  1273. f("`${b}`", asciiString("B"), t)
  1274. f("b.toString()", asciiString("B"), t)
  1275. f("b.valueOf()", valueTrue, t)
  1276. f("+b", intToValue(1), t)
  1277. })
  1278. var i testIntS = 1
  1279. t.Run("Int", func(t *testing.T) {
  1280. vm.Set("i", i)
  1281. f("`${i}`", asciiString("I"), t)
  1282. f("i.toString()", asciiString("I"), t)
  1283. f("i.valueOf()", intToValue(1), t)
  1284. f("+i", intToValue(1), t)
  1285. })
  1286. t.Run("*Int", func(t *testing.T) {
  1287. vm.Set("i", &i)
  1288. f("`${i}`", asciiString("I"), t)
  1289. f("i.toString()", asciiString("I"), t)
  1290. f("i.valueOf()", intToValue(1), t)
  1291. f("+i", intToValue(1), t)
  1292. })
  1293. var s testStringS
  1294. t.Run("String", func(t *testing.T) {
  1295. vm.Set("s", s)
  1296. f("`${s}`", asciiString("S"), t)
  1297. f("s.toString()", asciiString("S"), t)
  1298. f("s.valueOf()", asciiString("S"), t)
  1299. f("+s", _NaN, t)
  1300. })
  1301. t.Run("*String", func(t *testing.T) {
  1302. vm.Set("s", &s)
  1303. f("`${s}`", asciiString("S"), t)
  1304. f("s.toString()", asciiString("S"), t)
  1305. f("s.valueOf()", asciiString("S"), t)
  1306. f("+s", _NaN, t)
  1307. })
  1308. })
  1309. }
  1310. type testGoReflectFuncRt struct {
  1311. }
  1312. func (*testGoReflectFuncRt) M(call FunctionCall, r *Runtime) Value {
  1313. if r == nil {
  1314. panic(typeError("Runtime is nil"))
  1315. }
  1316. return call.Argument(0)
  1317. }
  1318. func (*testGoReflectFuncRt) C(call ConstructorCall, r *Runtime) *Object {
  1319. if r == nil {
  1320. panic(typeError("Runtime is nil in constructor"))
  1321. }
  1322. call.This.Set("r", call.Argument(0))
  1323. return nil
  1324. }
  1325. func TestGoReflectFuncWithRuntime(t *testing.T) {
  1326. vm := New()
  1327. var s testGoReflectFuncRt
  1328. vm.Set("s", &s)
  1329. res, err := vm.RunString("s.M(true)")
  1330. if err != nil {
  1331. t.Fatal(err)
  1332. }
  1333. if res != valueTrue {
  1334. t.Fatal(res)
  1335. }
  1336. res, err = vm.RunString("new s.C(true).r")
  1337. if err != nil {
  1338. t.Fatal(err)
  1339. }
  1340. if res != valueTrue {
  1341. t.Fatal(res)
  1342. }
  1343. }
  1344. func TestGoReflectDefaultToString(t *testing.T) {
  1345. var s testStringS
  1346. vm := New()
  1347. v := vm.ToValue(s).(*Object)
  1348. v.Delete("toString")
  1349. v.Delete("valueOf")
  1350. vm.Set("s", v)
  1351. _, err := vm.RunString(`
  1352. class S {
  1353. toString() {
  1354. return "X";
  1355. }
  1356. }
  1357. if (s.toString() !== "S") {
  1358. throw new Error(s.toString());
  1359. }
  1360. if (("" + s) !== "S") {
  1361. throw new Error("" + s);
  1362. }
  1363. Object.setPrototypeOf(s, S.prototype);
  1364. if (s.toString() !== "X") {
  1365. throw new Error(s.toString());
  1366. }
  1367. if (("" + s) !== "X") {
  1368. throw new Error("" + s);
  1369. }
  1370. `)
  1371. if err != nil {
  1372. t.Fatal(err)
  1373. }
  1374. }
  1375. func TestGoReflectUnexportedEmbedStruct(t *testing.T) {
  1376. type privateEmbed struct {
  1377. A string
  1378. }
  1379. type PublicEmbed struct {
  1380. B string
  1381. }
  1382. type privateNested struct {
  1383. C string
  1384. }
  1385. type PublicNested struct {
  1386. D string
  1387. }
  1388. type Foo struct {
  1389. privateEmbed
  1390. PublicEmbed
  1391. privateNested privateNested
  1392. PublicNested PublicNested
  1393. e string
  1394. F string
  1395. }
  1396. vm := New()
  1397. vm.Set("foo", Foo{
  1398. privateEmbed: privateEmbed{A: "testA"},
  1399. PublicEmbed: PublicEmbed{B: "testB"},
  1400. privateNested: privateNested{C: "testC"},
  1401. PublicNested: PublicNested{D: "testD"},
  1402. e: "testE",
  1403. F: "testF",
  1404. })
  1405. scenarios := []struct {
  1406. expr string
  1407. expected string
  1408. }{
  1409. {"foo.privateEmbed", "undefined"},
  1410. {"foo.A", "testA"},
  1411. // ---
  1412. {"foo.PublicEmbed", "[object Object]"},
  1413. {"foo.B", "testB"},
  1414. {"foo.PublicEmbed.B", "testB"},
  1415. // ---
  1416. {"foo.privateNested", "undefined"},
  1417. {"foo.C", "undefined"},
  1418. // ---
  1419. {"foo.PublicNested", "[object Object]"},
  1420. {"foo.D", "undefined"},
  1421. {"foo.PublicNested.D", "testD"},
  1422. // ---
  1423. {"foo.e", "undefined"},
  1424. {"foo.F", "testF"},
  1425. }
  1426. for _, s := range scenarios {
  1427. t.Run(s.expr, func(t *testing.T) {
  1428. v, err := vm.RunString(s.expr)
  1429. if err != nil {
  1430. t.Fatal(err)
  1431. }
  1432. vStr := v.String()
  1433. if vStr != s.expected {
  1434. t.Fatalf("Expected %q, got %q", s.expected, vStr)
  1435. }
  1436. })
  1437. }
  1438. }
  1439. func TestNestedSliceAddr(t *testing.T) {
  1440. type document struct {
  1441. Items []any
  1442. }
  1443. var d document
  1444. runtime := New()
  1445. runtime.Set("d", &d)
  1446. _, err := runtime.RunString(`
  1447. d.Items.push("Hello");
  1448. `)
  1449. if err != nil {
  1450. t.Fatal(err)
  1451. }
  1452. if len(d.Items) != 1 || d.Items[0] != "Hello" {
  1453. t.Fatal(d.Items)
  1454. }
  1455. }