<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
/* assert_array_equals() uses same_value() to compare each item, but
* Object.entries() returns an array of arrays, so we need to compare
* each item with assert_array_equals instead. */
function assert_record_equals(actual, expected, description) {
for (let i = 0; i < expected.length; ++i) {
assert_array_equals(Object.entries(actual)[i], expected[i], description);
}
}
test(() => {
let recordTest = internals.recordTest();
assert_throws_js(TypeError, () => {
recordTest.setStringLongRecord(null);
}, "Converting null to record should be rejected.");
assert_throws_js(TypeError, () => {
recordTest.setStringLongRecord(undefined);
}, "Converting undefined to record should be rejected.");
recordTest.setNullableStringLongRecord(null);
assert_equals(recordTest.getNullableStringLongRecord(),
null, "Passing null to a nullable record works");
recordTest.setNullableStringLongRecord(undefined);
assert_equals(recordTest.getNullableStringLongRecord(),
null, "Passing undefined to a nullable record works");
}, "Test handling of null and undefined records");
test(() => {
let recordTest = internals.recordTest();
let record = {'foo': 42, 'quux': 34};
let handler = {
getOwnPropertyDescriptor: (target, name) => {
if (name == 'quux')
return undefined;
return Reflect.getOwnPropertyDescriptor(target, name);
}
};
var recordProxy = new Proxy(record, handler);
recordTest.setStringLongRecord(record);
assert_record_equals(
recordTest.getStringLongRecord(), [['foo', 42]],
"Entries whose getOwnPropertyDescriptor return undefined are skipped");
}, "Test GetOwnPropertyDescriptor() returning undefined");
test(() => {
let recordTest = internals.recordTest();
recordTest.setStringLongRecord({a: true, false: null, c: "foo"});
assert_record_equals(recordTest.getStringLongRecord(),
[['a', 1], ['false', 0], ['c', 0]],
"Types are properly coerced to the record's types");
}, "Test type conversion");
test(() => {
let recordTest = internals.recordTest();
recordTest.setStringLongRecord({false: 1, [false]: 42});
assert_record_equals(recordTest.getStringLongRecord(), [['false', 42]],
"Key types are coerced and never repeated");
}, "Test duplicate keys");
test(() => {
let recordTest = internals.recordTest();
recordTest.setStringLongRecord({z: 42, foo: -5, ABC: 0});
assert_record_equals(recordTest.getStringLongRecord(),
[['z', 42], ['foo', -5], ['ABC', 0]],
"Keys are not sorted");
}, "Test mapping order");
test(() => {
let recordTest = internals.recordTest();
assert_throws_js(TypeError, () => {
recordTest.setByteStringByteStringRecord({'a': 'bc', '\uFFFF': 'foo'});
}, "Invalid ByteString key must throw a TypeError");
assert_throws_js(TypeError, () => {
recordTest.setByteStringByteStringRecord({'xy': 'z', 'foo': '\uFFFF'});
}, "Invalid ByteString value must throw a TypeError");
}, "Test ByteString validation");
test(() => {
let recordTest = internals.recordTest();
recordTest.setStringLongRecord({'foo': 0});
let record = recordTest.getStringLongRecord();
assert_record_equals(record, [['foo', 0]]);
record.baz = 'quux';
assert_equals(Object.keys(recordTest.getStringLongRecord()).length, 1,
"Changing a returned record does not change the record");
assert_record_equals(recordTest.getStringLongRecord(), [['foo', 0]],
"Changing a returned record does not change the record");
assert_record_equals(recordTest.getStringLongRecord(),
Object.entries(recordTest.getStringLongRecord()),
"Record getters always return the same elements");
assert_not_equals(recordTest.getStringLongRecord(), recordTest.getStringLongRecord(),
"Record getters always return a new copy");
}, "Test records are passed by value");
test(() => {
let recordTest = internals.recordTest();
assert_false(recordTest.unionReceivedARecord(true),
"Passing 'true' should convert the union to boolean");
assert_false(recordTest.unionReceivedARecord(false),
"Passing 'false' should convert the union to boolean");
assert_false(recordTest.unionReceivedARecord(42),
"Passing a number should convert the union to boolean");
assert_true(recordTest.unionReceivedARecord([1, 2, 3]),
"Passing an array should convert the union to a record");
assert_true(recordTest.unionReceivedARecord({}),
"Passing an object should conver the union to a record");
}, "Test unions resolve records");
test(() => {
let recordTest = internals.recordTest();
let elem = document.createElement('p');
recordTest.setStringElementRecord({'elem': elem});
assert_equals(recordTest.getStringElementRecord().elem, elem,
"The same DOM object was stored in the record");
assert_not_equals(recordTest.getStringElementRecord().elem,
document.createElement('p'),
"The same DOM object was stored in the record");
elem = document.createElement('br');
assert_not_equals(recordTest.getStringElementRecord().elem, elem,
"Changing the original value does not change the record value");
}, "Test DOM object types");
test(() => {
let recordTest = internals.recordTest();
let getterAlias = recordTest.getUSVStringUSVStringBooleanRecordRecord;
recordTest.setUSVStringUSVStringBooleanRecordRecord({'foo': {'bar': true}, 'quux': {'baz': false}});
let records = recordTest.getUSVStringUSVStringBooleanRecordRecord();
assert_array_equals(Object.keys(records), ['foo', 'quux'],
"Nested record types have the correct keys");
assert_record_equals(records.foo, [['bar', true]]);
assert_record_equals(records.quux, [['baz', false]]);
}, "Test nested record types");
test(() => {
let recordTest = internals.recordTest();
let record = recordTest.returnStringByteStringSequenceRecord();
assert_array_equals(Object.keys(record), ['foo', 'bar']);
assert_array_equals(record.foo, ['hello, world', 'hi, mom']);
assert_array_equals(record.bar, ['goodbye, mom']);
let other_record = recordTest.returnStringByteStringSequenceRecord();
assert_not_equals(record, other_record, "A new object is returned each time");
}, "Test sequences in records");
</script>