servo-script-bindings 0.3.0

A component of the servo web-engine.
Documentation
import WebIDL


def WebIDLTest(parser, harness):
    threw = False
    try:
        parser.parse(
            """
            interface Test {
              object toJSON();
            };
            """
        )
        parser.finish()
    except WebIDL.WebIDLError:
        threw = True
    harness.ok(not threw, "Should allow a toJSON method.")

    parser = parser.reset()
    threw = False
    try:
        parser.parse(
            """
            interface Test {
              object toJSON(object arg);
              object toJSON(long arg);
            };
            """
        )
        parser.finish()
    except WebIDL.WebIDLError:
        threw = True
    harness.ok(threw, "Should not allow overloads of a toJSON method.")

    parser = parser.reset()
    threw = False
    try:
        parser.parse(
            """
            interface Test {
              object toJSON(object arg);
            };
            """
        )
        parser.finish()
    except WebIDL.WebIDLError:
        threw = True
    harness.ok(threw, "Should not allow a toJSON method with arguments.")

    parser = parser.reset()
    threw = False
    try:
        parser.parse(
            """
            interface Test {
              long toJSON();
            };
            """
        )
        parser.finish()
    except WebIDL.WebIDLError:
        threw = True
    harness.ok(not threw, "Should allow a toJSON method with 'long' as return type.")

    parser = parser.reset()
    threw = False
    try:
        parser.parse(
            """
            interface Test {
              [Default] object toJSON();
            };
            """
        )
        parser.finish()
    except WebIDL.WebIDLError:
        threw = True
    harness.ok(
        not threw, "Should allow a default toJSON method with 'object' as return type."
    )

    parser = parser.reset()
    threw = False
    try:
        parser.parse(
            """
            interface Test {
              [Default] long toJSON();
            };
            """
        )
        parser.finish()
    except WebIDL.WebIDLError:
        threw = True
    harness.ok(
        threw,
        "Should not allow a default toJSON method with non-'object' as return type.",
    )

    JsonTypes = [
        "byte",
        "octet",
        "short",
        "unsigned short",
        "long",
        "unsigned long",
        "long long",
        "unsigned long long",
        "float",
        "unrestricted float",
        "double",
        "unrestricted double",
        "boolean",
        "DOMString",
        "ByteString",
        "UTF8String",
        "USVString",
        "Enum",
        "InterfaceWithToJSON",
        "object",
    ]

    nonJsonTypes = [
        "InterfaceWithoutToJSON",
        "any",
        "Int8Array",
        "Int16Array",
        "Int32Array",
        "Uint8Array",
        "Uint16Array",
        "Uint32Array",
        "Uint8ClampedArray",
        "Float32Array",
        "Float64Array",
        "ArrayBuffer",
    ]

    def doTest(testIDL, shouldThrow, description):
        p = parser.reset()
        threw = False
        try:
            p.parse(
                testIDL
                + """
                enum Enum { "a", "b", "c" };
                interface InterfaceWithToJSON { long toJSON(); };
                interface InterfaceWithoutToJSON {};
                """
            )
            p.finish()
        except Exception as x:
            threw = True
            harness.ok(x.message == "toJSON method has non-JSON return type", x)
        harness.check(threw, shouldThrow, description)

    for type in JsonTypes:
        doTest(
            f"interface Test {{ {type} toJSON(); }};",
            False,
            f"{type} should be a JSON type",
        )

        doTest(
            f"interface Test {{ sequence<{type}> toJSON(); }};",
            False,
            f"sequence<{type}> should be a JSON type",
        )

        doTest(
            f"dictionary Foo {{ {type} foo; }}; interface Test {{ Foo toJSON(); }}; ",
            False,
            f"dictionary containing only JSON type ({type}) should be a JSON type",
        )

        doTest(
            f"dictionary Foo {{ {type} foo; }}; dictionary Bar : Foo {{ }}; "
            "interface Test { Bar toJSON(); }; ",
            False,
            "dictionary whose ancestors only contain JSON types should be a JSON type",
        )

        doTest(
            f"dictionary Foo {{ any foo; }}; dictionary Bar : Foo {{ {type} bar; }};"
            "interface Test { Bar toJSON(); };",
            True,
            "dictionary whose ancestors contain non-JSON types should not be a JSON type",
        )

        doTest(
            f"interface Test {{ record<DOMString, {type}> toJSON(); }};",
            False,
            f"record<DOMString, {type}> should be a JSON type",
        )

        doTest(
            f"interface Test {{ record<ByteString, {type}> toJSON(); }};",
            False,
            f"record<ByteString, {type}> should be a JSON type",
        )

        doTest(
            f"interface Test {{ record<UTF8String, {type}> toJSON(); }};",
            False,
            f"record<UTF8String, {type}> should be a JSON type",
        )

        doTest(
            f"interface Test {{ record<USVString, {type}> toJSON(); }};",
            False,
            f"record<USVString, {type}> should be a JSON type",
        )

        otherUnionType = "Foo" if type != "object" else "long"
        doTest(
            "interface Foo { object toJSON(); };"
            f"interface Test {{ ({otherUnionType} or {type}) toJSON(); }};",
            False,
            f"union containing only JSON types ({otherUnionType} or {type}) should be a JSON type",
        )

        doTest(
            f"interface test {{ {type}? toJSON(); }};",
            False,
            f"Nullable type ({type}) should be a JSON type",
        )

        doTest(
            f"interface Foo : InterfaceWithoutToJSON {{ {type} toJSON(); }};"
            "interface Test { Foo toJSON(); };",
            False,
            "interface with toJSON should be a JSON type",
        )

    doTest(
        "interface Foo : InterfaceWithToJSON { };interface Test { Foo toJSON(); };",
        False,
        "inherited interface with toJSON should be a JSON type",
    )

    for type in nonJsonTypes:
        doTest(
            f"interface Test {{ {type} toJSON(); }};",
            True,
            f"{type} should not be a JSON type",
        )

        doTest(
            f"interface Test {{ sequence<{type}> toJSON(); }};",
            True,
            f"sequence<{type}> should not be a JSON type",
        )

        doTest(
            f"dictionary Foo {{ {type} foo; }}; interface Test {{ Foo toJSON(); }}; ",
            True,
            f"Dictionary containing a non-JSON type ({type}) should not be a JSON type",
        )

        doTest(
            f"dictionary Foo {{ {type} foo; }}; dictionary Bar : Foo {{ }}; "
            "interface Test { Bar toJSON(); }; ",
            True,
            "dictionary whose ancestors only contain non-JSON types should not be a JSON type",
        )

        doTest(
            f"interface Test {{ record<DOMString, {type}> toJSON(); }};",
            True,
            f"record<DOMString, {type}> should not be a JSON type",
        )

        doTest(
            f"interface Test {{ record<ByteString, {type}> toJSON(); }};",
            True,
            f"record<ByteString, {type}> should not be a JSON type",
        )

        doTest(
            f"interface Test {{ record<USVString, {type}> toJSON(); }};",
            True,
            f"record<USVString, {type}> should not be a JSON type",
        )

        if type != "any":
            doTest(
                "interface Foo { object toJSON(); }; "
                f"interface Test {{ (Foo or {type}) toJSON(); }};",
                True,
                f"union containing a non-JSON type ({type}) should not be a JSON type",
            )

            doTest(
                f"interface test {{ {type}? toJSON(); }};",
                True,
                f"Nullable type ({type}) should not be a JSON type",
            )

    doTest(
        "dictionary Foo { long foo; any bar; };interface Test { Foo toJSON(); };",
        True,
        "dictionary containing a non-JSON type should not be a JSON type",
    )

    doTest(
        "interface Foo : InterfaceWithoutToJSON { }; interface Test { Foo toJSON(); };",
        True,
        "interface without toJSON should not be a JSON type",
    )