seal.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. if (this.WScript && this.WScript.LoadScriptFile) { // Check for running in ch
  6. this.WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  7. }
  8. var tests = [
  9. {
  10. name: "Add, delete, modify properties after sealing",
  11. body: function () {
  12. let a = {x: 42};
  13. Object.seal(a);
  14. assert.isFalse(Object.isExtensible(a));
  15. assert.isTrue(Object.isSealed(a));
  16. // cannot add properties
  17. a.y = 17;
  18. assert.isFalse(a.hasOwnProperty('y'));
  19. assert.throws(function () { 'use strict'; a.y = 17; }, TypeError,
  20. "Should throw on creating a new property in sealed object in strict mode",
  21. "Cannot create property for a non-extensible object");
  22. // cannot delete properties
  23. assert.isFalse(delete a.x);
  24. assert.isTrue(a.hasOwnProperty('x'));
  25. assert.throws(function () { 'use strict'; delete a.x; }, TypeError,
  26. "Should throw on creating a new property in sealed object in strict mode",
  27. "Calling delete on 'x' is not allowed in strict mode");
  28. // cannot change prototype
  29. let b = {};
  30. assert.throws(function () { 'use strict'; Object.setPrototypeOf(a, b); }, TypeError,
  31. "Should throw on creating a new property in sealed object in strict mode",
  32. "Cannot create property for a non-extensible object");
  33. // ok to modify the existing property
  34. a.x = 17;
  35. assert.areEqual(17, a.x);
  36. }
  37. },
  38. {
  39. name: "Add, delete, modify indexed elements of an array after sealing",
  40. body: function () {
  41. let a = [42];
  42. a[2] = 43;
  43. Object.seal(a);
  44. assert.isFalse(Object.isExtensible(a));
  45. assert.isTrue(Object.isSealed(a));
  46. // the array cannot be extended
  47. a[3] = 17;
  48. assert.areEqual(3, a.length);
  49. assert.isFalse(a.hasOwnProperty('3'))
  50. assert.throws(function () { 'use strict'; a[3] = 17; }, TypeError,
  51. "Should throw on creating a new property in sealed object in strict mode",
  52. "Cannot create property for a non-extensible object");
  53. // a hole cannot be filled
  54. a[1] = 17;
  55. assert.areEqual(3, a.length);
  56. assert.isFalse(a.hasOwnProperty('1'))
  57. assert.throws(function () { 'use strict'; a[1] = 17; }, TypeError,
  58. "Should throw on creating a new property in sealed object in strict mode",
  59. "Cannot create property for a non-extensible object");
  60. // existing elements cannot be deleted
  61. assert.isFalse(delete a[0]);
  62. assert.isTrue(a.hasOwnProperty('0'));
  63. assert.throws(function () { 'use strict'; delete a[0]; }, TypeError,
  64. "Should throw on creating a new property in sealed object in strict mode",
  65. "Calling delete on '0' is not allowed in strict mode");
  66. // ok to modify an existing element
  67. a[0] = 17;
  68. assert.areEqual(17, a[0]);
  69. }
  70. },
  71. {
  72. name: "Add, delete, modify indexed elements of a typed array after sealing",
  73. body: function () {
  74. let a = new Int8Array(1);
  75. a[0] = 42;
  76. Object.seal(a);
  77. assert.isFalse(Object.isExtensible(a));
  78. assert.isTrue(Object.isSealed(a));
  79. /*
  80. Typed arrays never allow adding or removing elements - should we test
  81. that attempt to add in strict mode doesn't throw as for standard arrays?
  82. (that's the current behavior of v8 and Chakra)
  83. Not clear what the spec is.
  84. assert.throws(function () { 'use strict'; a[1] = 17; }, TypeError,
  85. "Should throw on creating a new property in sealed object in strict mode",
  86. "Cannot create property for a non-extensible object");
  87. */
  88. // ok to modify the existing element
  89. a[0] = 17;
  90. assert.areEqual(17, a[0]);
  91. }
  92. },
  93. {
  94. name: "Modify length of an array after sealing",
  95. body: function () {
  96. let a = [42, 17, 33];
  97. a.length = 4;
  98. Object.seal(a);
  99. let descr_len = Object.getOwnPropertyDescriptor(a, 'length');
  100. assert.isFalse(descr_len.configurable);
  101. assert.isTrue(descr_len.writable);
  102. // can increase length but cannot fill the tail
  103. a.length = 5;
  104. a[4] = "new!";
  105. assert.areEqual(5, a.length);
  106. assert.isFalse(a.hasOwnProperty('4'));
  107. // cannot truncate by reducing the length below the last defined element
  108. a.length = 1;
  109. assert.areEqual(3, a.length);
  110. }
  111. },
  112. {
  113. name: "Sealed versus frozen",
  114. body: function () {
  115. let a = {x: 42};
  116. Object.seal(a);
  117. assert.isTrue(Object.isSealed(a));
  118. assert.isFalse(Object.isFrozen(a));
  119. // https://tc39.github.io/ecma262/#sec-testintegritylevel (7.3.15)
  120. // empty objects are effectively frozen after being sealed
  121. let empty_obj = {};
  122. Object.seal(empty_obj);
  123. assert.isTrue(Object.isSealed(empty_obj));
  124. assert.isTrue(Object.isFrozen(empty_obj));
  125. // similar to above, a sealed object with all properties individually
  126. // set to non-writable and non-configurable is frozen
  127. let b = {};
  128. Object.defineProperty(b, 'x', { value: 42, writable: false });
  129. Object.seal(b);
  130. assert.isTrue(Object.isSealed(b));
  131. assert.isTrue(Object.isFrozen(b));
  132. // standard arrays
  133. let arr = [42];
  134. Object.seal(arr);
  135. assert.isTrue(Object.isSealed(arr));
  136. assert.isFalse(Object.isFrozen(arr));
  137. // typed arrays
  138. let ta = new Int8Array(4);
  139. Object.seal(ta);
  140. assert.isTrue(Object.isSealed(ta));
  141. assert.isFalse(Object.isFrozen(ta));
  142. // empty typed arrays are effectively frozen after being sealed
  143. let ta_empty = new Int8Array(0);
  144. Object.seal(ta_empty);
  145. assert.isTrue(Object.isSealed(ta_empty));
  146. assert.isTrue(Object.isFrozen(ta_empty));
  147. // frozen objects are sealed
  148. let c = {x: 42};
  149. Object.freeze(c);
  150. assert.isTrue(Object.isFrozen(c));
  151. assert.isTrue(Object.isSealed(c));
  152. }
  153. },
  154. ];
  155. testRunner.runTests(tests, { verbose: false /*so no need to provide baseline*/ });