async executeWithControlFlow(inputs, context, outputNames, isFunctionExecution) {
        const names = Object.keys(inputs);
        const inputNodes = names.map((name)=>this.graph.nodes[(0, _utils.parseNodeName)(name)[0]]);
        const outputNodeNames = outputNames.map((name)=>(0, _utils.parseNodeName)(name)[0]);
        const outputNodeNameSet = new Set(outputNodeNames);
        let outputNodes = outputNodeNames.map((name)=>this.graph.nodes[name]);
        // If no outputs are specified, then use the default outputs of the model.
        if (outputNodes.length === 0) outputNodes = this._outputs;
        const { usedNodes, missingInputs, dynamicNode, syncInputs } = (0, _modelAnalysis.getExecutionSubgraph)(inputs, outputNodes, this.weightMap, this._initNodes);
        // First nodes to execute include inputNodes, weights, and initNodes.
        const stack = [
            ...inputNodes,
            ...this.graph.weights,
            ...this._initNodes || []
        ].map((node)=>{
            return {
                node,
                contexts: context.currentContext
            };
        });
        const tensorsMap = Object.assign({}, this.weightMap);
        Object.keys(inputs).forEach((name)=>{
            const [nodeName, index] = (0, _utils.parseNodeName)(name);
            const tensors = [];
            tensors[index] = inputs[name];
            tensorsMap[nodeName] = tensors;
        });
        const intermediateTensorConsumerCount = {};
        const tensorsToKeep = this.getFrozenTensorIds(tensorsMap);
        const added = {};
        while(stack.length > 0){
            const promises = this.processStack(inputNodes, stack, context, tensorsMap, added, tensorsToKeep, outputNodeNameSet, intermediateTensorConsumerCount, usedNodes);
            await Promise.all(promises);
        }
        if (dynamicNode == null && !isFunctionExecution) console.warn(`This model execution did not contain any nodes with control flow ` + `or dynamic output shapes. You can use model.execute() instead.`);
        const missingOutputs = outputNodes.filter((node)=>!(0, _modelAnalysis.isControlFlow)(node) && !(0, _utils.getTensor)(node.name, tensorsMap, context)).map((node)=>node.name);
        if (missingOutputs.length > 0) {
            let alternativeMsg = "";
            if (dynamicNode != null) alternativeMsg = `Alternatively, to avoid the dynamic ops, use model.execute() ` + `and specify the inputs [${syncInputs}]`;
            throw new Error(`Cannot compute the outputs [${missingOutputs}] from the provided ` + `inputs [${names}]. Consider providing the following inputs: ` + `[${missingInputs}]. ${alternativeMsg}`);
        }
        return tensorsMap;
    }
When there are control flow nodes in the graph, the graph execution use
ExecutionContext to keep track of the frames and loop iterators.
@param inputs placeholder tensors for the graph.
@param context the execution context object for current execution.
@param outputNames Optional. output node name from the Tensorflow model,
if no outputs are specified, the default outputs of the model would be
used. You can inspect intermediate nodes of the model by adding them to
the outputs array.
@param isFunctionExecution Flag for executing a function.