for-in-basic.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. test("iterate through empty string", () => {
  2. const a = [];
  3. for (const property in "") {
  4. a.push(property);
  5. }
  6. expect(a).toEqual([]);
  7. });
  8. test("iterate through number", () => {
  9. const a = [];
  10. for (const property in 123) {
  11. a.push(property);
  12. }
  13. expect(a).toEqual([]);
  14. });
  15. test("iterate through empty object", () => {
  16. const a = [];
  17. for (const property in {}) {
  18. a.push(property);
  19. }
  20. expect(a).toEqual([]);
  21. });
  22. test("iterate through string", () => {
  23. const a = [];
  24. for (const property in "hello") {
  25. a.push(property);
  26. }
  27. expect(a).toEqual(["0", "1", "2", "3", "4"]);
  28. });
  29. test("iterate through object", () => {
  30. const a = [];
  31. for (const property in { a: 1, b: 2, c: 2 }) {
  32. a.push(property);
  33. }
  34. expect(a).toEqual(["a", "b", "c"]);
  35. });
  36. test("iterate through undefined", () => {
  37. for (const property in undefined) {
  38. expect.fail();
  39. }
  40. });
  41. test("use already-declared variable", () => {
  42. var property;
  43. for (property in "abc");
  44. expect(property).toBe("2");
  45. });
  46. test("allow binding patterns", () => {
  47. const expected = [
  48. ["1", "3", []],
  49. ["s", undefined, []],
  50. ["l", "n", ["g", "N", "a", "m", "e"]],
  51. ];
  52. let counter = 0;
  53. for (let [a, , b, ...c] in { 123: 1, sm: 2, longName: 3 }) {
  54. expect(a).toBe(expected[counter][0]);
  55. expect(b).toBe(expected[counter][1]);
  56. expect(c).toEqual(expected[counter][2]);
  57. counter++;
  58. }
  59. expect(counter).toBe(3);
  60. });
  61. describe("special left hand sides", () => {
  62. test("allow member expression as variable", () => {
  63. const f = {};
  64. for (f.a in "abc");
  65. expect(f.a).toBe("2");
  66. });
  67. test("allow member expression of function call", () => {
  68. const b = {};
  69. function f() {
  70. return b;
  71. }
  72. for (f().a in "abc");
  73. expect(f().a).toBe("2");
  74. expect(b.a).toBe("2");
  75. });
  76. test("call function is allowed in parsing but fails in runtime", () => {
  77. function f() {
  78. expect().fail();
  79. }
  80. // Does not fail since it does not iterate
  81. expect("for (f() in []);").toEvalTo(undefined);
  82. expect(() => {
  83. eval("for (f() in [0]) { expect().fail() }");
  84. }).toThrowWithMessage(ReferenceError, "Invalid left-hand side in assignment");
  85. });
  86. });
  87. test("remove properties while iterating", () => {
  88. const from = [1, 2, 3];
  89. const to = [];
  90. for (const prop in from) {
  91. to.push(prop);
  92. from.pop();
  93. }
  94. expect(to).toEqual(["0", "1"]);
  95. });
  96. test("duplicated properties in prototype", () => {
  97. const object = { a: 1 };
  98. const proto = { a: 2 };
  99. Object.setPrototypeOf(object, proto);
  100. const a = [];
  101. for (const prop in object) {
  102. a.push(prop);
  103. }
  104. expect(a).toEqual(["a"]);
  105. });