summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/streams/transferable/reason.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/streams/transferable/reason.html')
-rw-r--r--testing/web-platform/tests/streams/transferable/reason.html132
1 files changed, 132 insertions, 0 deletions
diff --git a/testing/web-platform/tests/streams/transferable/reason.html b/testing/web-platform/tests/streams/transferable/reason.html
new file mode 100644
index 0000000000..4251aa85b8
--- /dev/null
+++ b/testing/web-platform/tests/streams/transferable/reason.html
@@ -0,0 +1,132 @@
+<!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>