function visitComponent(mainType, dependencies) {

            var newCptOptionList = normalizeToArray(newOption[mainType]);

            var mapResult = mappingToExists(
                componentsMap.get(mainType), newCptOptionList
            );

            makeIdAndName(mapResult);

            // Set mainType and complete subType.
            each$1(mapResult, function (item, index) {
                var opt = item.option;
                if (isObject$1(opt)) {
                    item.keyInfo.mainType = mainType;
                    item.keyInfo.subType = determineSubType(mainType, opt, item.exist);
                }
            });

            var dependentModels = getComponentsByTypes(
                componentsMap, dependencies
            );

            option[mainType] = [];
            componentsMap.set(mainType, []);

            each$1(mapResult, function (resultItem, index) {
                var componentModel = resultItem.exist;
                var newCptOption = resultItem.option;

                assert$1(
                    isObject$1(newCptOption) || componentModel,
                    'Empty component definition'
                );

                // Consider where is no new option and should be merged using {},
                // see removeEdgeAndAdd in topologicalTravel and
                // ComponentModel.getAllClassMainTypes.
                if (!newCptOption) {
                    componentModel.mergeOption({}, this);
                    componentModel.optionUpdated({}, false);
                }
                else {
                    var ComponentModelClass = ComponentModel.getClass(
                        mainType, resultItem.keyInfo.subType, true
                    );

                    if (componentModel && componentModel.constructor === ComponentModelClass) {
                        componentModel.name = resultItem.keyInfo.name;
                        // componentModel.settingTask && componentModel.settingTask.dirty();
                        componentModel.mergeOption(newCptOption, this);
                        componentModel.optionUpdated(newCptOption, false);
                    }
                    else {
                        // PENDING Global as parent ?
                        var extraOpt = extend(
                            {
                                dependentModels: dependentModels,
                                componentIndex: index
                            },
                            resultItem.keyInfo
                        );
                        componentModel = new ComponentModelClass(
                            newCptOption, this, this, extraOpt
                        );
                        extend(componentModel, extraOpt);
                        componentModel.init(newCptOption, this, this, extraOpt);

                        // Call optionUpdated after init.
                        // newCptOption has been used as componentModel.option
                        // and may be merged with theme and default, so pass null
                        // to avoid confusion.
                        componentModel.optionUpdated(null, true);
                    }
                }

                componentsMap.get(mainType)[index] = componentModel;
                option[mainType][index] = componentModel.option;
            }, this);

            // Backup series for filtering.
            if (mainType === 'series') {
                createSeriesIndices(this, componentsMap.get('series'));
            }
        }
@param {string} mainType
@param {number} [idx=0]
@return {module:echarts/model/Component}