| <!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'); |
| shouldBeNull('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', '[]'); |
| shouldBeNull('dict.stringSequenceOrNullMember'); |
| shouldBeUndefined('dict.elementMember'); |
| shouldBeUndefined('dict.elementOrNullMember'); |
| shouldBeUndefined('dict.enumMember'); |
| shouldBeEqualToString('dict.enumMemberWithDefault', 'foo'); |
| shouldBeNull('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'); |
| shouldBeNull('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', '[]'); |
| shouldBeNull('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. |
| shouldBeNull('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 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 [ImplementedAs] and [DeprecateAs] member'); |
| dictionaryTest.set({ |
| deprecateLongMember: 42 |
| }); |
| dict = dictionaryTest.get(); |
| shouldBe('dict.longMember', '42'); |
| 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 passing Dictionary (not IDL dictionary)'); |
| dictionaryTest.set({ |
| dictionaryMember: {'foo': 'x', 'bar': 'y'} |
| }); |
| properties = dictionaryTest.getDictionaryMemberProperties(); |
| shouldBeEqualToString('properties.foo', 'x'); |
| shouldBeEqualToString('properties.bar', 'y'); |
| shouldBeUndefined('properties.baz'); |
| dictionaryTest.set({dictionaryMember: undefined}); |
| properties = dictionaryTest.getDictionaryMemberProperties(); |
| shouldBe('properties', '{}'); |
| shouldThrow("dictionaryTest.set({dictionaryMember: 42})"); |
| shouldThrow("dictionaryTest.set({dictionaryMember: 'foo'})"); |
| debug(''); |
| |
| debug('Test for derived dictionary'); |
| dictionaryTest.setDerived({ requiredBooleanMember: true }); |
| derived = dictionaryTest.getDerived(); |
| shouldBeUndefined('derived.longMember'); |
| shouldBe('derived.longMemberWithDefault', '42'); |
| shouldBeNull('derived.longOrNullMember'); |
| shouldBeNull('derived.longOrNullMemberWithDefault'); |
| shouldBeUndefined('derived.booleanMember'); |
| shouldBeUndefined('derived.doubleMember'); |
| shouldBeUndefined('derived.stringMember'); |
| shouldBeEqualToString('derived.stringMemberWithDefault', 'defaultStringValue'); |
| shouldBeUndefined('derived.stringSequenceMember'); |
| shouldBe('derived.stringSequenceMemberWithDefault', '[]'); |
| shouldBeNull('derived.stringSequenceOrNullMember'); |
| shouldBeUndefined('derived.elementMember'); |
| shouldBeUndefined('derived.elementOrNullMember'); |
| shouldBeUndefined('derived.enumMember'); |
| shouldBeEqualToString('derived.enumMemberWithDefault', 'foo'); |
| shouldBeNull('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> |