<!DOCTYPE HTML>
<html>
<head>
<title>IdlArray.prototype.is_json_type()</title>
</head>
<body>
<div id="log"></div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
<script src="/resources/idlharness.js"></script>
<script src="../../../idl-helper.js"></script>
<script>
    "use strict";

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("DOMString")));
        assert_true(idl.is_json_type(typeFrom("ByteString")));
        assert_true(idl.is_json_type(typeFrom("USVString")));
        idl.add_untested_idls('enum BarEnum { "a", "b", "c" };');
        assert_true(idl.is_json_type(typeFrom("BarEnum")));
    }, 'should return true for all string types');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("Error")));
        assert_false(idl.is_json_type(typeFrom("DOMException")));
    }, 'should return false for all exception types');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("Int8Array")));
        assert_false(idl.is_json_type(typeFrom("Int16Array")));
        assert_false(idl.is_json_type(typeFrom("Int32Array")));
        assert_false(idl.is_json_type(typeFrom("Uint8Array")));
        assert_false(idl.is_json_type(typeFrom("Uint16Array")));
        assert_false(idl.is_json_type(typeFrom("Uint32Array")));
        assert_false(idl.is_json_type(typeFrom("Uint8ClampedArray")));
        assert_false(idl.is_json_type(typeFrom("BigInt64Array")));
        assert_false(idl.is_json_type(typeFrom("BigUint64Array")));
        assert_false(idl.is_json_type(typeFrom("Float32Array")));
        assert_false(idl.is_json_type(typeFrom("Float64Array")));
        assert_false(idl.is_json_type(typeFrom("ArrayBuffer")));
        assert_false(idl.is_json_type(typeFrom("DataView")));
    }, 'should return false for all buffer source types');

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("boolean")));
    }, 'should return true for boolean');

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("byte")));
        assert_true(idl.is_json_type(typeFrom("octet")));
        assert_true(idl.is_json_type(typeFrom("short")));
        assert_true(idl.is_json_type(typeFrom("unsigned short")));
        assert_true(idl.is_json_type(typeFrom("long")));
        assert_true(idl.is_json_type(typeFrom("unsigned long")));
        assert_true(idl.is_json_type(typeFrom("long long")));
        assert_true(idl.is_json_type(typeFrom("unsigned long long")));
        assert_true(idl.is_json_type(typeFrom("float")));
        assert_true(idl.is_json_type(typeFrom("unrestricted float")));
        assert_true(idl.is_json_type(typeFrom("double")));
        assert_true(idl.is_json_type(typeFrom("unrestricted double")));
    }, 'should return true for all numeric types');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("Promise<DOMString>")));
    }, 'should return false for promises');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("sequence<DOMException>")));
        assert_true(idl.is_json_type(typeFrom("sequence<DOMString>")));
    }, 'should handle sequences according to their inner types');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("FrozenArray<DOMException>")));
        assert_true(idl.is_json_type(typeFrom("FrozenArray<DOMString>")));
    }, 'should handle frozen arrays according to their inner types');

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("record<DOMString, DOMString>")));
        assert_false(idl.is_json_type(typeFrom("record<DOMString, Error>")));
    }, 'should handle records according to their inner types');

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("object")));
    }, 'should return true for object type');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("any")));
    }, 'should return false for any type');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('dictionary Foo { DOMString foo; }; dictionary Bar : Foo { DOMString bar; };');
        assert_true(idl.is_json_type(typeFrom("Foo")));
        assert_true(idl.is_json_type(typeFrom("Bar")));
    }, 'should return true for dictionaries whose members are all JSON types');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('dictionary Foo { };');
        assert_true(idl.is_json_type(typeFrom("Foo")));
    }, 'should return true for dictionaries which have no members');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('dictionary FooBar { DOMString a; Error b; }; dictionary Baz : FooBar {};');
        assert_false(idl.is_json_type(typeFrom("FooBar")));
        assert_false(idl.is_json_type(typeFrom("Baz")));
    }, 'should return false for dictionaries whose members are not all JSON types');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('interface Foo { DOMString toJSON(); };');
        assert_true(idl.is_json_type(typeFrom("Foo")));
    }, 'should return true for interfaces which declare a toJSON operation');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('interface Foo { DOMString toJSON(); }; interface Bar : Foo { };');
        assert_true(idl.is_json_type(typeFrom("Bar")));
    }, 'should return true for interfaces which inherit from an interface which declares a toJSON operation');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('interface Foo { }; interface mixin Bar { DOMString toJSON(); }; Foo includes Bar;');
        idl.merge_mixins();
        assert_true(idl.is_json_type(typeFrom("Foo")));
    }, 'should return true for interfaces which mixin an interface which declare a toJSON operation');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('interface Foo { };');
        assert_false(idl.is_json_type(typeFrom("Foo")));
    }, 'should return false for interfaces which do not declare a toJSON operation');

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('interface Foo { object toJSON(); };');
        assert_true(idl.is_json_type(typeFrom("(Foo or DOMString)")));
    }, 'should return true for union types whose member types are JSON types');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typeFrom("(DataView or DOMString)")));
    }, 'should return false for union types whose member types are not all JSON types');

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("DOMString?")));
        assert_false(idl.is_json_type(typeFrom("DataView?")));
    }, 'should consider the inner types of nullable types');

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typeFrom("[XAttr] long")));
        assert_false(idl.is_json_type(typeFrom("[XAttr] DataView")));
    }, 'should consider the inner types of annotated types.');

    test(function() {
        var idl = new IdlArray();
        assert_throws_js(Error, _ => idl.is_json_type(typeFrom("Foo")));
    }, "should throw if it references a dictionary, enum or interface which wasn't added to the IdlArray");

    test(function() {
        var idl = new IdlArray();
        idl.add_untested_idls('interface Foo : Bar { };');
        assert_throws_js(Error, _ => idl.is_json_type(typeFrom("Foo")));
    }, "should throw for interfaces which inherit from another interface which wasn't added to the IdlArray");

    test(function() {
        var idl = new IdlArray();
        assert_true(idl.is_json_type(typedefFrom("typedef double DOMHighResTimeStamp;").idlType));
    }, 'should return true for typedefs whose source type is a JSON type');

    test(function() {
        var idl = new IdlArray();
        assert_false(idl.is_json_type(typedefFrom("typedef DataView DOMHighResTimeStamp;").idlType));
    }, 'should return false for typedefs whose source type is not a JSON type');
</script>
</body>
</html>
