<!DOCTYPE html>
<script src="../resources/js-test.js"></script>
<script>
description('IDL dictionary unittest');
var testObject1 = { foo: 'x' };
var testObject2 = { bar: 'y' };
if (window.internals && internals.dictionaryTest) {
var dictionaryTest = internals.dictionaryTest();
debug('Test for setting an empty dictionary');
dictionaryTest.set({});
dict = dictionaryTest.get();
shouldBeUndefined('dict.longMember');
shouldBe('dict.longMemberWithDefault', '42');
shouldBeUndefined('dict.longOrNullMember');
shouldBeNull('dict.longOrNullMemberWithDefault');
shouldBeUndefined('dict.booleanMember');
shouldBeUndefined('dict.doubleMember');
shouldBeUndefined('dict.unrestrictedDoubleMember');
shouldBeUndefined('dict.stringMember');
shouldBeEqualToString('dict.stringMemberWithDefault', 'defaultStringValue');
shouldBeUndefined('dict.byteStringMember');
shouldBeUndefined('dict.usvStringMember');
shouldBeUndefined('dict.stringSequenceMember');
shouldBe('dict.stringSequenceMemberWithDefault', '[]');
shouldBeUndefined('dict.stringSequenceOrNullMember');
shouldBeUndefined('dict.elementMember');
shouldBeUndefined('dict.elementOrNullMember');
shouldBeUndefined('dict.enumMember');
shouldBeEqualToString('dict.enumMemberWithDefault', 'foo');
shouldBeUndefined('dict.enumOrNullMember');
shouldBeUndefined('dict.objectMember');
shouldBeNull('dict.objectOrNullMemberWithDefault');
shouldBeUndefined('dict.doubleOrStringMember');
shouldBeUndefined('dict.doubleOrStringSequenceMember');
shouldBeNull('dict.eventTargetOrNullMember');
shouldBeUndefined('dict.anyMember');
shouldBeUndefined('dict.callbackFunctionMember');
debug('');
debug('Test for setting undefined');
dictionaryTest.set(undefined);
dict = dictionaryTest.get();
shouldBeUndefined('dict.longMember');
shouldBe('dict.longMemberWithDefault', '42');
shouldBeUndefined('dict.longOrNullMember');
shouldBeNull('dict.longOrNullMemberWithDefault');
shouldBeUndefined('dict.booleanMember');
shouldBeUndefined('dict.doubleMember');
shouldBeUndefined('dict.unrestrictedDoubleMember');
shouldBeUndefined('dict.stringMember');
shouldBeUndefined('dict.byteStringMember');
shouldBeUndefined('dict.usvStringMember');
shouldBeEqualToString('dict.stringMemberWithDefault', 'defaultStringValue');
shouldBeUndefined('dict.stringSequenceMember');
shouldBe('dict.stringSequenceMemberWithDefault', '[]');
shouldBeUndefined('dict.stringSequenceOrNullMember');
shouldBeUndefined('dict.elementMember');
shouldBeUndefined('dict.elementOrNullMember');
shouldBeUndefined('dict.objectMember');
shouldBeNull('dict.objectOrNullMemberWithDefault');
shouldBeNull('dict.eventTargetOrNullMember');
shouldBeUndefined('dict.anyMember');
shouldBeUndefined('dict.callbackFunctionMember');
debug('');
var element1 = document.createElement('div');
debug('Test for setting valid values');
dictionaryTest.set({
longMember: 1,
longMemberWithDefault: 2,
longOrNullMember: 3,
longOrNullMemberWithDefault: 4,
stringMember: 'modifiedString1',
stringMemberWithDefault: 'modifiedString2',
byteStringMember: '\x00\x01\xFE\xFF',
usvStringMember: '!@#123ABCabc\xA0\uD800\uDC00',
booleanMember: true,
doubleMember: 3.14,
unrestrictedDoubleMember: NaN,
stringSequenceMember: ['foo', 'bar', 'baz'],
stringSequenceMemberWithDefault: ['foo', 'bar', 'baz'],
stringSequenceOrNullMember: [],
elementMember: element1,
elementOrNullMember: null,
enumMember: 'foo',
enumMemberWithDefault: 'bar',
enumOrNullMember: 'baz',
objectMember: testObject1,
objectOrNullMemberWithDefault: testObject2,
doubleOrStringMember: 3.14,
doubleOrStringSequenceMember: [3.14, 'Hello'],
eventTargetOrNullMember: element1,
internalEnumOrInternalEnumSequenceMember: 'foo',
anyMember: 42,
callbackFunctionMember: (arg1, arg2) => { return 'Hi ' + arg1 + ' and ' + arg2; },
});
dict = dictionaryTest.get();
shouldBe('dict.longMember', '1');
shouldBe('dict.longMemberWithDefault', '2');
shouldBe('dict.longOrNullMember', '3');
shouldBe('dict.longOrNullMemberWithDefault', '4');
shouldBeEqualToString('dict.stringMember', 'modifiedString1');
shouldBeEqualToString('dict.stringMemberWithDefault', 'modifiedString2');
shouldBeEqualToString('dict.byteStringMember', '\x00\x01\xFE\xFF');
shouldBeEqualToString('dict.usvStringMember', '!@#123ABCabc\xA0\uD800\uDC00');
shouldBeTrue('dict.booleanMember');
shouldBe('dict.doubleMember', '3.14');
shouldBe('dict.unrestrictedDoubleMember', 'NaN');
shouldBe('dict.stringSequenceMember', '["foo", "bar", "baz"]');
shouldBe('dict.stringSequenceMemberWithDefault', '["foo", "bar", "baz"]');
shouldBe('dict.stringSequenceOrNullMember', '[]');
shouldBe('dict.elementMember', 'element1');
shouldBeNull('dict.elementOrNullMember');
shouldBeEqualToString('dict.enumMember', 'foo');
shouldBeEqualToString('dict.enumMemberWithDefault', 'bar');
shouldBeEqualToString('dict.enumOrNullMember', 'baz');
shouldBe('dict.objectMember', 'testObject1');
shouldBe('dict.objectOrNullMemberWithDefault', 'testObject2');
shouldBe('dict.doubleOrStringMember', '3.14');
shouldBe('dict.doubleOrStringSequenceMember', '[3.14, "Hello"]');
shouldBe('dict.eventTargetOrNullMember', 'element1');
shouldBeEqualToString('dict.internalEnumOrInternalEnumSequenceMember', 'foo');
shouldBe('dict.anyMember', '42');
shouldBeEqualToString('dict.callbackFunctionMember("A", "B")', 'Hi A and B');
debug('');
debug('Additional test for union type members');
dictionaryTest.set({
doubleOrStringMember: "foo",
});
dict = dictionaryTest.get();
shouldBeEqualToString('dict.doubleOrStringMember', 'foo');
dictionaryTest.set({
doubleOrStringMember: {},
});
dict = dictionaryTest.get();
shouldBeEqualToString('dict.doubleOrStringMember', '[object Object]');
dictionaryTest.set({
doubleOrStringMember: [],
});
dict = dictionaryTest.get();
shouldBeEqualToString('dict.doubleOrStringMember', '');
dictionaryTest.set({
doubleOrStringMember: null,
});
dict = dictionaryTest.get();
shouldBeEqualToString('dict.doubleOrStringMember', 'null');
dictionaryTest.set({
doubleOrStringMember: undefined,
});
dict = dictionaryTest.get();
shouldBeUndefined('dict.doubleOrStringMember');
dictionaryTest.set({
internalEnumOrInternalEnumSequenceMember: ['foo', 'bar'],
});
dict = dictionaryTest.get();
shouldBe('dict.internalEnumOrInternalEnumSequenceMember', '["foo", "bar"]');
debug('');
debug('Test for explicit undefined or null, and missing members');
dictionaryTest.set({
enumOrNullMember: null,
longMember: undefined,
longMemberWithDefault: null,
longOrNullMember: undefined,
longOrNullMemberWithDefault: null,
});
dict = dictionaryTest.get();
shouldBeNull('dict.enumOrNullMember');
shouldBeUndefined('dict.longMember');
// ToNumber(null) results in 0.
shouldBe('dict.longMemberWithDefault', '0');
// Passing undefined shouldn't invoke any conversion.
shouldBeUndefined('dict.longOrNullMember');
// Nullable and its default value is null
shouldBeNull('dict.longOrNullMemberWithDefault');
// A non-nullable enum must throw when passed null.
shouldThrow('dictionaryTest.set({enumMember: null})');
debug('');
debug('Test for different values for the any type');
dictionaryTest.set({
anyMember: '',
});
dict = dictionaryTest.get();
shouldBeEmptyString('dict.anyMember');
dictionaryTest.set({
anyMember: 0,
});
dict = dictionaryTest.get();
shouldBeZero('dict.anyMember');
dictionaryTest.set({
anyMember: undefined,
});
dict = dictionaryTest.get();
shouldBeUndefined('dict.anyMember');
dictionaryTest.set({
anyMember: false,
});
dict = dictionaryTest.get();
shouldBeFalse('dict.anyMember');
dictionaryTest.set({
anyMember: null,
});
dict = dictionaryTest.get();
shouldBeNull('dict.anyMember');
debug('');
debug('Test for setting invalid member');
dictionaryTest.set({invalidMember: 'shouldNotBeSet'});
dict = dictionaryTest.get();
shouldBeUndefined('dict.invalidMember');
debug('');
debug('Test for setting invalid double value');
shouldThrow("dictionaryTest.set({doubleMember: NaN})");
shouldThrow("dictionaryTest.set({doubleMember: Infinity})");
shouldThrow("dictionaryTest.set({doubleMember: -Infinity})");
shouldThrow("dictionaryTest.set({doubleMember: 'invalid'})");
debug('');
debug('Test for setting invalid ByteString value');
shouldThrow("dictionaryTest.set({byteStringMember: '\u0100'})");
debug('');
debug('Test for setting invalid USVString value');
dictionaryTest.set({usvStringMember: '_\uDC00_\uD800_\uDC00\uD800_'});
dict = dictionaryTest.get();
shouldBeEqualToString('dict.usvStringMember', '_\uFFFD_\uFFFD_\uFFFD\uFFFD_');
debug('Test for setting invalid enum value');
shouldThrow("dictionaryTest.set({enumMember: 'invalid'})");
debug('');
debug('Test for setting invalid enum value in union sequence');
shouldThrow("dictionaryTest.set({internalEnumOrInternalEnumSequenceMember: 'invalid'})");
shouldThrow("dictionaryTest.set({internalEnumOrInternalEnumSequenceMember: ['invalid']})");
debug('Test for setting invalid object value');
shouldThrow("dictionaryTest.set({objectMember: 42})");
shouldThrow("dictionaryTest.set({objectMember: 'invalid'})");
debug('');
debug('Test for setting invalid Element value');
shouldThrow("dictionaryTest.set({elementMember: 42})");
shouldThrow("dictionaryTest.set({elementMember: testObject1})");
shouldThrow("dictionaryTest.set({elementMember: []})");
shouldThrow("dictionaryTest.set({elementMember: document})");
debug('');
debug('Test for setting invalid callback function value');
shouldThrow("dictionaryTest.set({callbackFunctionMember: {}})");
debug('');
debug('Test for passing invalid dictionary values');
shouldThrow("dictionaryTest.set(42)");
shouldThrow("dictionaryTest.set('string')");
debug('');
debug('Test for [Clamp] and [EnforceRange] member');
dictionaryTest.set({
longMember: 2147483648,
longMemberWithClamp: 2147483648
});
dict = dictionaryTest.get();
shouldBe('dict.longMember', '-2147483648');
shouldBe('dict.longMemberWithClamp', '2147483647');
shouldThrow('dictionaryTest.set({ longMemberWithEnforceRange: 2147483648 })');
debug('');
debug('Test for passing EventTarget');
dictionaryTest.set({
eventTargetOrNullMember: window
});
dict = dictionaryTest.get();
shouldBe('dict.eventTargetOrNullMember', 'window');
dictionaryTest.set({
eventTargetOrNullMember: null
});
dict = dictionaryTest.get();
shouldBeNull('dict.eventTargetOrNullMember');
dictionaryTest.set({
eventTargetOrNullMember: undefined
});
dict = dictionaryTest.get();
shouldBeNull('dict.eventTargetOrNullMember');
shouldThrow("dictionaryTest.set({eventTargetOrNullMember: 'invalid'})");
shouldThrow("dictionaryTest.set({eventTargetOrNullMember: 42})");
shouldThrow("dictionaryTest.set({eventTargetOrNullMember: []})");
shouldThrow("dictionaryTest.set({eventTargetOrNullMember: {}})");
debug('');
debug('Test for derived dictionary');
dictionaryTest.setDerived({ requiredBooleanMember: true });
derived = dictionaryTest.getDerived();
shouldBeUndefined('derived.longMember');
shouldBe('derived.longMemberWithDefault', '42');
shouldBeUndefined('derived.longOrNullMember');
shouldBeNull('derived.longOrNullMemberWithDefault');
shouldBeUndefined('derived.booleanMember');
shouldBeUndefined('derived.doubleMember');
shouldBeUndefined('derived.stringMember');
shouldBeEqualToString('derived.stringMemberWithDefault', 'defaultStringValue');
shouldBeUndefined('derived.stringSequenceMember');
shouldBe('derived.stringSequenceMemberWithDefault', '[]');
shouldBeUndefined('derived.stringSequenceOrNullMember');
shouldBeUndefined('derived.elementMember');
shouldBeUndefined('derived.elementOrNullMember');
shouldBeUndefined('derived.enumMember');
shouldBeEqualToString('derived.enumMemberWithDefault', 'foo');
shouldBeUndefined('derived.enumOrNullMember');
shouldBeUndefined('derived.objectMember');
shouldBeNull('derived.objectOrNullMemberWithDefault');
shouldBeUndefined('derived.derivedStringMember');
shouldBeEqualToString('derived.derivedStringMemberWithDefault', 'derivedDefaultStringValue');
shouldBeTrue('derived.requiredBooleanMember');
debug('');
dictionaryTest.setDerived({
longMember: 1,
stringMemberWithDefault: 'modifiedString',
derivedStringMember: 'modifiedString2',
derivedStringMemberWithDefault: 'modifiedString3',
invalidMember: 'shouldNotBeSet',
requiredBooleanMember: false,
});
derived = dictionaryTest.getDerived();
shouldBe('derived.longMember', '1');
shouldBeEqualToString('derived.stringMemberWithDefault', 'modifiedString');
shouldBeEqualToString('derived.derivedStringMember', 'modifiedString2');
shouldBeEqualToString('derived.derivedStringMemberWithDefault', 'modifiedString3');
shouldBeUndefined('derived.invalidMember');
shouldBeFalse('derived.requiredBooleanMember');
debug('');
debug('Test for triple level derived dictionary');
dictionaryTest.setDerivedDerived({
longMember: 1,
derivedStringMember: 'modifiedString',
derivedDerivedStringMember: 'modifiedString2',
requiredBooleanMember: false,
});
derived = dictionaryTest.getDerivedDerived();
shouldBe('derived.longMember', '1');
shouldBeEqualToString('derived.derivedStringMember', 'modifiedString');
shouldBeEqualToString('derived.derivedDerivedStringMember', 'modifiedString2');
shouldBeFalse('derived.requiredBooleanMember');
debug('');
debug('Test for passing invalid values as derived dictionary');
shouldThrow("dictionaryTest.setDerived({objectMember: 42, requiredBooleanMember: false })");
shouldThrow("dictionaryTest.setDerived({})"); // Missing required member.
}
</script>