error_cause.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  7. function makeTestsFor(ErrorConstructor, options) {
  8. const name = options ? options.getNameOfConstructor() : ErrorConstructor.name;
  9. const prototype = options ? options.getPrototypeOfConstructor() : ErrorConstructor.prototype;
  10. const rawConstructor = options ? options.rawConstructor : ErrorConstructor
  11. const message = "Test message";
  12. const o = {};
  13. return [
  14. {
  15. name: `"cause" in ${ name }.prototype.cause === false`,
  16. body: function () {
  17. assert.isFalse("cause" in prototype, `Cause property must not exist in ${ name }.prototype`);
  18. }
  19. },
  20. {
  21. name: `"cause" in ${ name }().cause === false`,
  22. body: function () {
  23. assert.isFalse("cause" in ErrorConstructor(), `${ name }().cause should not be defined if not specified by cause property of options parameter in ${ name } constructor`);
  24. }
  25. },
  26. {
  27. name: `message property is defined when ${ name } called with one argument, not cause`,
  28. body: function () {
  29. assert.isTrue("message" in ErrorConstructor(message), `message property is defined when ${ name } called with one argument, not cause`);
  30. assert.isTrue(ErrorConstructor(message).message === message, `message property is defined when ${ name } called with one argument, not cause`);
  31. assert.isFalse("cause" in ErrorConstructor(message), `message property is defined when ${ name } called with one argument, not cause`);
  32. }
  33. },
  34. {
  35. name: `${ name }(${ message }, { cause: o })'s descriptor`,
  36. body: function () {
  37. const e = ErrorConstructor(message, { cause: o });
  38. const desc = Object.getOwnPropertyDescriptor(e, "cause");
  39. assert.areEqual(desc.configurable, true, "e.cause should be configurable");
  40. assert.areEqual(desc.writable, true, "e.cause should be writable");
  41. assert.areEqual(desc.enumerable, false, "e.cause should not be enumerable");
  42. }
  43. },
  44. {
  45. name: `o === ${ name }(${ message }, { cause: o }).cause`,
  46. body: function () {
  47. const e = Error();
  48. assert.areEqual(ErrorConstructor("", { cause: o }).cause, o, `Cause property value should be kept as-is`);
  49. assert.areEqual(ErrorConstructor("", { cause: 0 }).cause, 0, `Cause property value should be kept as-is`);
  50. assert.areEqual(ErrorConstructor("", { cause: e }).cause, e, `Cause property value should be kept as-is`);
  51. assert.areEqual(ErrorConstructor("", { cause: "A cause" }).cause, "A cause", `Cause property value should be kept as-is`);
  52. }
  53. },
  54. {
  55. name: "Options with cause property as getter",
  56. body: function () {
  57. var getCounter = 0;
  58. const options = {
  59. get cause() {
  60. getCounter++;
  61. return o;
  62. }
  63. }
  64. ErrorConstructor(message, options);
  65. assert.areEqual(getCounter, 1, `getCounter should be 1`);
  66. }
  67. },
  68. {
  69. name: "Options with cause property as getter which throws",
  70. body: function () {
  71. const options = {
  72. get cause() {
  73. throw ErrorConstructor();
  74. }
  75. }
  76. assert.throws(() => ErrorConstructor(message, options), rawConstructor);
  77. }
  78. },
  79. {
  80. name: "Proxy options parameter",
  81. body: function () {
  82. const options = new Proxy({ cause: o }, {
  83. has(target, p) {
  84. hasCounter++;
  85. return p in target;
  86. },
  87. get(target, p) {
  88. getCounter++;
  89. return target[p];
  90. }
  91. });
  92. var hasCounter = 0, getCounter = 0;
  93. const e = ErrorConstructor("test", options);
  94. assert.areEqual(hasCounter, 1, `hasCounter should be 1`);
  95. assert.areEqual(getCounter, 1, `getCounter should be 1`);
  96. assert.areEqual(e.cause, o, `Cause property value should be kept as-is`);
  97. assert.areEqual(hasCounter, 1, `hasCounter should be 1`);
  98. assert.areEqual(getCounter, 1, `getCounter should be 1`);
  99. }
  100. },
  101. {
  102. name: "Cause property is not added to error if options parameter doesn't have the cause property",
  103. body: function () {
  104. assert.isFalse('cause' in ErrorConstructor(message, { }), `Cause property must not be added to error if options parameter doesn't have the cause property`);
  105. }
  106. },
  107. {
  108. name: "Cause property is not added to error if options parameter isn't typeof object",
  109. body: function () {
  110. Number.prototype.cause = 0;
  111. String.prototype.cause = 0;
  112. assert.isFalse('cause' in ErrorConstructor(message, 0), `Cause property must not be added to error if options parameter isn't typeof object`);
  113. assert.isFalse('cause' in ErrorConstructor(message, ""), `Cause property must not be added to error if options parameter isn't typeof object`);
  114. }
  115. }
  116. ]
  117. }
  118. const tests = [
  119. ...makeTestsFor(Error),
  120. ...makeTestsFor(TypeError),
  121. ...makeTestsFor(ReferenceError),
  122. ...makeTestsFor(SyntaxError),
  123. ...makeTestsFor(RangeError),
  124. ...makeTestsFor(EvalError),
  125. ...makeTestsFor((message, options) => AggregateError([], message, options), {
  126. getNameOfConstructor: () => AggregateError.name,
  127. getPrototypeOfConstructor: () => AggregateError.prototype,
  128. rawConstructor: AggregateError
  129. })
  130. ];
  131. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });