| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="resources/helpers.js"></script> |
| <script> |
| 'use strict'; |
| |
| // Chrome used to special-case the reason for cancel() and abort() in order to |
| // handle exceptions correctly. This is no longer necessary. These tests are |
| // retained to avoid regressions. |
| |
| async function getTransferredReason(originalReason) { |
| let resolvePromise; |
| const rv = new Promise(resolve => { |
| resolvePromise = resolve; |
| }); |
| const rs = await createTransferredReadableStream({ |
| cancel(reason) { |
| resolvePromise(reason); |
| } |
| }); |
| await rs.cancel(originalReason); |
| return rv; |
| } |
| |
| for (const value of ['hi', '\t\r\n', 7, 3.0, undefined, null, true, false, |
| NaN, Infinity]) { |
| promise_test(async () => { |
| const reason = await getTransferredReason(value); |
| assert_equals(reason, value, 'reason should match'); |
| }, `reason with a simple value of '${value}' should be preserved`); |
| } |
| |
| for (const badType of [Symbol('hi'), _ => 'hi']) { |
| promise_test(async t => { |
| return promise_rejects_dom(t, 'DataCloneError', |
| getTransferredReason(badType), |
| 'cancel() should reject'); |
| }, `reason with a type of '${typeof badType}' should be rejected and ` + |
| `error the stream`); |
| } |
| |
| promise_test(async () => { |
| const reasonAsJson = |
| `{"foo":[1,"col"],"bar":{"hoge":0.2,"baz":{},"shan":null}}`; |
| const reason = await getTransferredReason(JSON.parse(reasonAsJson)); |
| assert_equals(JSON.stringify(reason), reasonAsJson, |
| 'object should be preserved'); |
| }, 'objects that can be completely expressed in JSON should be preserved'); |
| |
| promise_test(async () => { |
| const circularObject = {}; |
| circularObject.self = circularObject; |
| const reason = await getTransferredReason(circularObject); |
| assert_true(reason instanceof Object, 'an Object should be output'); |
| assert_equals(reason.self, reason, |
| 'the object should have a circular reference'); |
| }, 'objects that cannot be expressed in JSON should also be preserved'); |
| |
| promise_test(async () => { |
| const originalReason = new TypeError('hi'); |
| const reason = await getTransferredReason(originalReason); |
| assert_true(reason instanceof TypeError, |
| 'type should be preserved'); |
| assert_equals(reason.message, originalReason.message, |
| 'message should be preserved'); |
| }, 'the type and message of a TypeError should be preserved'); |
| |
| promise_test(async () => { |
| const originalReason = new TypeError('hi'); |
| originalReason.foo = 'bar'; |
| const reason = await getTransferredReason(originalReason); |
| assert_false('foo' in reason, |
| 'foo should not be preserved'); |
| }, 'other attributes of a TypeError should not be preserved'); |
| |
| promise_test(async () => { |
| const originalReason = new TypeError(); |
| originalReason.message = [1, 2, 3]; |
| const reason = await getTransferredReason(originalReason); |
| assert_equals(reason.message, '1,2,3', 'message should be stringified'); |
| }, 'a TypeError message should be converted to a string'); |
| |
| promise_test(async () => { |
| const originalReason = new TypeError(); |
| Object.defineProperty(originalReason, 'message', { |
| get() { return 'words'; } |
| }); |
| const reason = await getTransferredReason(originalReason); |
| assert_equals(reason.message, '', 'message should not be preserved'); |
| }, 'a TypeError message should not be preserved if it is a getter'); |
| |
| promise_test(async () => { |
| const originalReason = new TypeError(); |
| delete originalReason.message; |
| TypeError.prototype.message = 'inherited message'; |
| const reason = await getTransferredReason(originalReason); |
| delete TypeError.prototype.message; |
| assert_equals(reason.message, '', 'message should not be preserved'); |
| }, 'a TypeError message should not be preserved if it is inherited'); |
| |
| promise_test(async () => { |
| const originalReason = new DOMException('yes', 'AbortError'); |
| const reason = await getTransferredReason(originalReason); |
| assert_true(reason instanceof DOMException, |
| 'reason should be a DOMException'); |
| assert_equals(reason.message, originalReason.message, |
| 'the messages should match'); |
| assert_equals(reason.name, originalReason.name, |
| 'the names should match'); |
| }, 'DOMException errors should be preserved'); |
| |
| for (const errorConstructor of [EvalError, RangeError, |
| ReferenceError, SyntaxError, TypeError, |
| URIError]) { |
| promise_test(async () => { |
| const originalReason = new errorConstructor('nope'); |
| const reason = await getTransferredReason(originalReason); |
| assert_equals(typeof reason, 'object', 'reason should have type object'); |
| assert_true(reason instanceof errorConstructor, |
| `reason should inherit ${errorConstructor.name}`); |
| assert_true(reason instanceof Error, 'reason should inherit Error'); |
| assert_equals(reason.constructor, errorConstructor, |
| 'reason should have the right constructor'); |
| assert_equals(reason.name, errorConstructor.name, |
| `name should match constructor name`); |
| assert_equals(reason.message, 'nope', 'message should match'); |
| }, `${errorConstructor.name} should be preserved`); |
| } |
| |
| </script> |