| <!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 = window.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'); | 
 |     shouldBeNull('dict.elementOrNullMember'); | 
 |     shouldBeUndefined('dict.enumMember'); | 
 |     shouldBeUndefined('dict.enumArrayMember'); | 
 |     shouldBeEqualToString('dict.enumMemberWithDefault', 'foo'); | 
 |     shouldBeNull('dict.enumOrNullMember'); | 
 |     shouldBeUndefined('dict.objectMember'); | 
 |     shouldBeNull('dict.objectOrNullMemberWithDefault'); | 
 |     shouldBeUndefined('dict.doubleOrStringMember'); | 
 |     shouldBeUndefined('dict.doubleOrStringSequenceMember'); | 
 |     shouldBeNull('dict.eventTargetOrNullMember'); | 
 |     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'); | 
 |     shouldBeNull('dict.elementOrNullMember'); | 
 |     shouldBeUndefined('dict.objectMember'); | 
 |     shouldBeNull('dict.objectOrNullMemberWithDefault'); | 
 |     shouldBeNull('dict.eventTargetOrNullMember'); | 
 |     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', | 
 |         enumArrayMember: ['foo', 'bar', 'baz'], | 
 |         objectMember: testObject1, | 
 |         objectOrNullMemberWithDefault: testObject2, | 
 |         doubleOrStringMember: 3.14, | 
 |         doubleOrStringSequenceMember: [3.14, 'Hello'], | 
 |         eventTargetOrNullMember: element1 | 
 |     }); | 
 |     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'); | 
 |     // This will be undefined as the spec says | 
 |     shouldBeNull('dict.elementOrNullMember'); | 
 |     shouldBeEqualToString('dict.enumMember', 'foo'); | 
 |     shouldBeEqualToString('dict.enumMemberWithDefault', 'bar'); | 
 |     shouldBeEqualToString('dict.enumOrNullMember', 'baz'); | 
 |     shouldBe('dict.enumArrayMember', '["foo", "bar", "baz"]'); | 
 |     shouldBe('dict.objectMember', 'testObject1'); | 
 |     shouldBe('dict.objectOrNullMemberWithDefault', 'testObject2'); | 
 |     shouldBe('dict.doubleOrStringMember', '3.14'); | 
 |     shouldBe('dict.doubleOrStringSequenceMember', '[3.14, "Hello"]'); | 
 |     shouldBe('dict.eventTargetOrNullMember', 'element1'); | 
 |     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'); | 
 |  | 
 |     debug(''); | 
 |  | 
 |     debug('Test for explicit undefined or null, and missing members'); | 
 |     dictionaryTest.set({ | 
 |         longMember: undefined, | 
 |         longMemberWithDefault: null, | 
 |         longOrNullMember: undefined, | 
 |         longOrNullMemberWithDefault: null, | 
 |     }); | 
 |     dict = dictionaryTest.get(); | 
 |     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'); | 
 |     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'})"); | 
 |     shouldThrow("dictionaryTest.set({enumArrayMember: ['foo', 'invalid', 'baz']})"); | 
 |     debug(''); | 
 |  | 
 |     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'); | 
 |     shouldBeNull('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> |