function validateNodesExecutionOrder(orderedNodes, predefinedNodes) {
    const nodeNameToOrder = new Map(orderedNodes.map((node, order)=>[
            node.name,
            order
        ]));
    const predefinedNodeNames = new Set(predefinedNodes.map((node)=>node.name));
    const isPredefined = (node)=>predefinedNodeNames.has(typeof node === "string" ? node : node.name);
    const willBeExecutedNodeNames = new Set(orderedNodes.map((node)=>node.name));
    const willBeExecuted = (node)=>willBeExecutedNodeNames.has(typeof node === "string" ? node : node.name);
    for (const node of orderedNodes){
        for (const child of node.children.filter(willBeExecuted)){
            if (!nodeNameToOrder.has(child.name)) throw new NodesExecutionOrderError(`Child ${child.name} of node ${node.name} is unreachable.`);
            if (nodeNameToOrder.get(node.name) > nodeNameToOrder.get(child.name)) throw new NodesExecutionOrderError(`Node ${node.name} is scheduled to run after its child ${child.name}.`);
        }
        if (!isPredefined(node)) for (const input of node.inputs){
            if (!nodeNameToOrder.has(input.name)) throw new NodesExecutionOrderError(`Input ${input.name} of node ${node.name} is unreachable.`);
            if (nodeNameToOrder.get(input.name) > nodeNameToOrder.get(node.name)) throw new NodesExecutionOrderError(`Node ${node.name} is scheduled to run before its input ${input.name}.`);
        }
    }
}
This is a helper function of `getNodesInTopologicalOrder`.
Validates property: given nodes `a` and `b`, Order(a) > Order(b) if `a`
is a child of `b`. This function throws an error if validation fails.

@param orderedNodes Graph nodes in execution order.
@param predefinedNodes Graph inputs, weights, and init nodes. Nodes in this
    list must have distinct names.