object_gomap_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. package goja
  2. import "testing"
  3. func TestGomapProp(t *testing.T) {
  4. const SCRIPT = `
  5. o.a + o.b;
  6. `
  7. r := New()
  8. r.Set("o", map[string]interface{}{
  9. "a": 40,
  10. "b": 2,
  11. })
  12. v, err := r.RunString(SCRIPT)
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. if i := v.ToInteger(); i != 42 {
  17. t.Fatalf("Expected 42, got: %d", i)
  18. }
  19. }
  20. func TestGomapEnumerate(t *testing.T) {
  21. const SCRIPT = `
  22. var hasX = false;
  23. var hasY = false;
  24. for (var key in o) {
  25. switch (key) {
  26. case "x":
  27. if (hasX) {
  28. throw "Already have x";
  29. }
  30. hasX = true;
  31. break;
  32. case "y":
  33. if (hasY) {
  34. throw "Already have y";
  35. }
  36. hasY = true;
  37. break;
  38. default:
  39. throw "Unexpected property: " + key;
  40. }
  41. }
  42. hasX && hasY;
  43. `
  44. r := New()
  45. r.Set("o", map[string]interface{}{
  46. "x": 40,
  47. "y": 2,
  48. })
  49. v, err := r.RunString(SCRIPT)
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. if !v.StrictEquals(valueTrue) {
  54. t.Fatalf("Expected true, got %v", v)
  55. }
  56. }
  57. func TestGomapDeleteWhileEnumerate(t *testing.T) {
  58. const SCRIPT = `
  59. var hasX = false;
  60. var hasY = false;
  61. for (var key in o) {
  62. switch (key) {
  63. case "x":
  64. if (hasX) {
  65. throw "Already have x";
  66. }
  67. hasX = true;
  68. delete o.y;
  69. break;
  70. case "y":
  71. if (hasY) {
  72. throw "Already have y";
  73. }
  74. hasY = true;
  75. delete o.x;
  76. break;
  77. default:
  78. throw "Unexpected property: " + key;
  79. }
  80. }
  81. hasX && !hasY || hasY && !hasX;
  82. `
  83. r := New()
  84. r.Set("o", map[string]interface{}{
  85. "x": 40,
  86. "y": 2,
  87. })
  88. v, err := r.RunString(SCRIPT)
  89. if err != nil {
  90. t.Fatal(err)
  91. }
  92. if !v.StrictEquals(valueTrue) {
  93. t.Fatalf("Expected true, got %v", v)
  94. }
  95. }
  96. func TestGomapInstanceOf(t *testing.T) {
  97. const SCRIPT = `
  98. (o instanceof Object) && !(o instanceof Error);
  99. `
  100. r := New()
  101. r.Set("o", map[string]interface{}{})
  102. v, err := r.RunString(SCRIPT)
  103. if err != nil {
  104. t.Fatal(err)
  105. }
  106. if !v.StrictEquals(valueTrue) {
  107. t.Fatalf("Expected true, got %v", v)
  108. }
  109. }
  110. func TestGomapTypeOf(t *testing.T) {
  111. const SCRIPT = `
  112. typeof o;
  113. `
  114. r := New()
  115. r.Set("o", map[string]interface{}{})
  116. v, err := r.RunString(SCRIPT)
  117. if err != nil {
  118. t.Fatal(err)
  119. }
  120. if !v.StrictEquals(asciiString("object")) {
  121. t.Fatalf("Expected object, got %v", v)
  122. }
  123. }
  124. func TestGomapProto(t *testing.T) {
  125. const SCRIPT = `
  126. o.hasOwnProperty("test");
  127. `
  128. r := New()
  129. r.Set("o", map[string]interface{}{
  130. "test": 42,
  131. })
  132. v, err := r.RunString(SCRIPT)
  133. if err != nil {
  134. t.Fatal(err)
  135. }
  136. if !v.StrictEquals(valueTrue) {
  137. t.Fatalf("Expected true, got %v", v)
  138. }
  139. }
  140. func TestGoMapExtensibility(t *testing.T) {
  141. const SCRIPT = `
  142. "use strict";
  143. o.test = 42;
  144. Object.preventExtensions(o);
  145. o.test = 43;
  146. try {
  147. o.test1 = 42;
  148. } catch (e) {
  149. if (!(e instanceof TypeError)) {
  150. throw e;
  151. }
  152. }
  153. o.test === 43 && o.test1 === undefined;
  154. `
  155. r := New()
  156. r.Set("o", map[string]interface{}{})
  157. v, err := r.RunString(SCRIPT)
  158. if err != nil {
  159. if ex, ok := err.(*Exception); ok {
  160. t.Fatal(ex.String())
  161. } else {
  162. t.Fatal(err)
  163. }
  164. }
  165. if !v.StrictEquals(valueTrue) {
  166. t.Fatalf("Expected true, got %v", v)
  167. }
  168. }
  169. func TestGoMapWithProto(t *testing.T) {
  170. vm := New()
  171. m := map[string]interface{}{
  172. "t": "42",
  173. }
  174. vm.Set("m", m)
  175. vm.testScriptWithTestLib(`
  176. (function() {
  177. 'use strict';
  178. var proto = {};
  179. var getterAllowed = false;
  180. var setterAllowed = false;
  181. var tHolder = "proto t";
  182. Object.defineProperty(proto, "t", {
  183. get: function() {
  184. if (!getterAllowed) throw new Error("getter is called");
  185. return tHolder;
  186. },
  187. set: function(v) {
  188. if (!setterAllowed) throw new Error("setter is called");
  189. tHolder = v;
  190. }
  191. });
  192. var t1Holder;
  193. Object.defineProperty(proto, "t1", {
  194. get: function() {
  195. return t1Holder;
  196. },
  197. set: function(v) {
  198. t1Holder = v;
  199. }
  200. });
  201. Object.setPrototypeOf(m, proto);
  202. assert.sameValue(m.t, "42");
  203. m.t = 43;
  204. assert.sameValue(m.t, 43);
  205. t1Holder = "test";
  206. assert.sameValue(m.t1, "test");
  207. m.t1 = "test1";
  208. assert.sameValue(m.t1, "test1");
  209. delete m.t;
  210. getterAllowed = true;
  211. assert.sameValue(m.t, "proto t", "after delete");
  212. setterAllowed = true;
  213. m.t = true;
  214. assert.sameValue(m.t, true);
  215. assert.sameValue(tHolder, true);
  216. Object.preventExtensions(m);
  217. assert.throws(TypeError, function() {
  218. m.t2 = 1;
  219. });
  220. m.t1 = "test2";
  221. assert.sameValue(m.t1, "test2");
  222. })();
  223. `, _undefined, t)
  224. }
  225. func TestGoMapProtoProp(t *testing.T) {
  226. const SCRIPT = `
  227. (function() {
  228. "use strict";
  229. var proto = {};
  230. Object.defineProperty(proto, "ro", {value: 42});
  231. Object.setPrototypeOf(m, proto);
  232. assert.throws(TypeError, function() {
  233. m.ro = 43;
  234. });
  235. Object.defineProperty(m, "ro", {value: 43});
  236. assert.sameValue(m.ro, 43);
  237. })();
  238. `
  239. r := New()
  240. r.Set("m", map[string]interface{}{})
  241. r.testScriptWithTestLib(SCRIPT, _undefined, t)
  242. }
  243. func TestGoMapProtoPropChain(t *testing.T) {
  244. const SCRIPT = `
  245. (function() {
  246. "use strict";
  247. var p1 = Object.create(null);
  248. m.__proto__ = p1;
  249. Object.defineProperty(p1, "test", {
  250. value: 42
  251. });
  252. Object.defineProperty(m, "test", {
  253. value: 43,
  254. writable: true,
  255. });
  256. var o = Object.create(m);
  257. o.test = 44;
  258. assert.sameValue(o.test, 44);
  259. var sym = Symbol(true);
  260. Object.defineProperty(p1, sym, {
  261. value: 42
  262. });
  263. Object.defineProperty(m, sym, {
  264. value: 43,
  265. writable: true,
  266. });
  267. o[sym] = 44;
  268. assert.sameValue(o[sym], 44);
  269. })();
  270. `
  271. r := New()
  272. r.Set("m", map[string]interface{}{})
  273. r.testScriptWithTestLib(SCRIPT, _undefined, t)
  274. }
  275. func TestGoMapUnicode(t *testing.T) {
  276. const SCRIPT = `
  277. Object.setPrototypeOf(m, s);
  278. if (m.Тест !== "passed") {
  279. throw new Error("m.Тест: " + m.Тест);
  280. }
  281. m["é"];
  282. `
  283. type S struct {
  284. Тест string
  285. }
  286. vm := New()
  287. m := map[string]interface{}{
  288. "é": 42,
  289. }
  290. s := S{
  291. Тест: "passed",
  292. }
  293. vm.Set("m", m)
  294. vm.Set("s", &s)
  295. res, err := vm.RunString(SCRIPT)
  296. if err != nil {
  297. t.Fatal(err)
  298. }
  299. if res == nil || !res.StrictEquals(valueInt(42)) {
  300. t.Fatalf("Unexpected value: %v", res)
  301. }
  302. }