for-in-basic.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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.xfailIf(
  77. isBytecodeInterpreterEnabled(),
  78. "call function is allowed in parsing but fails in runtime",
  79. () => {
  80. function f() {
  81. expect().fail();
  82. }
  83. // Does not fail since it does not iterate
  84. expect("for (f() in []);").toEvalTo(undefined);
  85. expect(() => {
  86. eval("for (f() in [0]) { expect().fail() }");
  87. }).toThrowWithMessage(ReferenceError, "Invalid left-hand side in assignment");
  88. }
  89. );
  90. test.xfailIf(
  91. isBytecodeInterpreterEnabled(),
  92. "Cannot change constant declaration in body",
  93. () => {
  94. const vals = [];
  95. for (const v in [1, 2]) {
  96. expect(() => v++).toThrowWithMessage(
  97. TypeError,
  98. "Invalid assignment to const variable"
  99. );
  100. vals.push(v);
  101. }
  102. expect(vals).toEqual(["0", "1"]);
  103. }
  104. );
  105. });
  106. test("remove properties while iterating", () => {
  107. const from = [1, 2, 3];
  108. const to = [];
  109. for (const prop in from) {
  110. to.push(prop);
  111. from.pop();
  112. }
  113. expect(to).toEqual(["0", "1"]);
  114. });
  115. test("duplicated properties in prototype", () => {
  116. const object = { a: 1 };
  117. const proto = { a: 2 };
  118. Object.setPrototypeOf(object, proto);
  119. const a = [];
  120. for (const prop in object) {
  121. a.push(prop);
  122. }
  123. expect(a).toEqual(["a"]);
  124. });