private let mojoBuiltins: [String: ILType] = [
    /// Profiles declare this method, a wrapper method around `getRemote` that follows
    /// the Singleton pattern, in `codePrefix`. This method ensures: (1) `getRemote`
    /// is only called once, and (2) the remote is saved to a global variable so it
    /// can be closed at the end of the program.
    "getOrCreatePrimaryRemote": .function([] => .{{primary|format_il_type}}),
{%- for receiver in interface_receivers %}
    "{{receiver|fully_qualified_name}}CallbackRouter":
       .constructor([] => .js{{receiver|format_unique_name}}CallbackRouter),
{%- endfor %}
{%- for struct in structs %}
    "{{struct|fully_qualified_name}}": .{{struct|format_il_type}}Constructor,
{%- endfor %}
]

private let keepGenerators = [
    "IntegerGenerator", "StringGenerator", "TernaryOperationGenerator",
    "PlainFunctionGenerator", "AsyncFunctionGenerator", "AwaitGenerator",
    "SubroutineReturnGenerator", "TryCatchGenerator",
]

private let mojoDisabledGenerators: [String] = CodeGenerators.map { $0.name }
    .filter {
        !keepGenerators.contains($0)
    }

let mojo{{primary.name}}Profile = Profile(
    processArgs: { _ in return [] },
    processArgsReference: nil,
    processEnv: [
        "ASAN_OPTIONS": "detect_odr_violation=0:abort_on_error=1", "DISPLAY": ":20",
    ],
    maxExecsBeforeRespawn: 1000,
    timeout: Timeout.interval(11000, 11000),
    codePrefix: """
        let globalRemote = null;
        function getOrCreatePrimaryRemote() {
            if (!globalRemote) {
                globalRemote = {{primary|fully_qualified_name}}.getRemote();
            }
            return globalRemote;
        }
        """,
    codeSuffix: "if (globalRemote) {globalRemote.$.close()}",
    ecmaVersion: v8Profile.ecmaVersion,
    startupTests: [
        ("fuzzilli('FUZZILLI_PRINT', 'test')", .shouldSucceed),
        (
            """
            if (typeof {{(primary.module.namespace|namespace_as_array)[0]}} == 'undefined' \
            || {{((primary.module.namespace|namespace_as_array)+ [primary.name]) | join('?.')}} === undefined) \
            throw '{{primary.name}} not found'
            """,
            .shouldSucceed
        ),
    ] + v8Profile.startupTests,
    additionalCodeGenerators: [
        (MojoMethodCallGenerator, 10000),
        (MojoPropertyRetrievalGenerator, 10000),
{%- for receiver in interface_receivers %}
    {%- if receiver.methods %}
        (Mojo{{receiver|format_unique_name}}RouterListenerGenerator, 5000),
    {%- endif %}
{%- endfor %}
{%- for array in arrays %}
        (Mojo{{array|format_unique_name}}Generator, 1),
{%- endfor %}
    ] + commonMojoCodeGenerators,
    additionalProgramTemplates: WeightedList([]),
    disabledCodeGenerators: mojoDisabledGenerators,
    disabledMutators: [
        "ExplorationMutator", "ProbingMutator", "PropertyAccessorMutator"
    ],
    additionalBuiltins: mojoBuiltins.merging(commonMojoBuiltins) { (existing, _) in existing },
    additionalObjectGroups: [
{%- for remote in interface_remotes %}
        .{{remote|format_unique_name|to_camel(True)}}Remote,
        .{{remote|format_unique_name|to_camel(True)}}RemoteWrapper,
        .{{remote|format_unique_name|to_camel(True)}}PendingReceiver,
{%- endfor %}
{%- for receiver in interface_receivers %}
        .{{receiver|format_unique_name|to_camel(True)}}CallbackRouter,
        .{{receiver|format_unique_name|to_camel(True)}}CallbackRouterReceiverHelper,
        .{{receiver|format_unique_name|to_camel(True)}}Remote,
        .{{receiver|format_unique_name|to_camel(True)}}RemoteWrapper,
        .{{receiver|format_unique_name|to_camel(True)}}PendingReceiver,
        {%- for method in receiver.methods %}
        .{{(method|callback_receiver_name)|to_camel(True)}},
        {%- endfor %}
{%- endfor %}
{%- for struct in structs + response_structs %}
        .{{struct|format_unique_name|to_camel(True)}},
{%- endfor %}
    ] + commonMojoObjectGroups,
    additionalEnumerations: [
{%- for enum in enums %}
        .{{enum|format_il_type}},
{%- endfor %}
    ] + commonMojoEnumerations,
    additionalOptionsBags: [
{%- for union in unions %}
        .{{union|format_unique_name|to_camel(True)}},
{%- endfor %}
    ] + commonMojoOptionsBags,
    optionalPostProcessor: nil
)
