Repository: chartjs/Chart.js
File: src/core/core.datasetController.js (JavaScript)

Code before:
		// In order to correctly handle data addition/deletion animation (an thus simulate
		// real-time charts), we need to monitor these data modifications and synchronize
		// the internal meta data accordingly.
		if (me._data !== data) {
			if (me._data) {
				// This case happens when the user replaced the data array instance.
				unlistenArrayEvents(me._data, me);
			}

			listenArrayEvents(data, me);
			me._data = data;
		}

		// Re-sync meta data in case the user replaced the data array or if we missed
		// any updates and so make sure that we handle number of datapoints changing.
		me.resyncElements();
	},

	/**
	 * Returns the default dataset-level options
	 * @private
	 */
	_defaults: function() {
		var me = this;
		var dataset = me.getDataset();
		var type = helpers.valueOrDefault(dataset.type, me.chart.config.type);
		return defaults.datasets[type];
	},

	update: helpers.noop,

	transition: function(easingValue) {
		var meta = this.getMeta();
		var elements = meta.data || [];
		var ilen = elements.length;
		var i = 0;

		for (; i < ilen; ++i) {
			elements[i].transition(easingValue);
		}

		if (meta.dataset) {
			meta.dataset.transition(easingValue);
		}
	},

	draw: function() {
		var meta = this.getMeta();
		var elements = meta.data || [];
		var ilen = elements.length;
		var i = 0;

Review comment (bug):
We shouldn't "resolve" the dataset type because (if I'm not wrong) [it's already part of the dataset meta](/chartjs/Chart.js/blob/master/src/core/core.controller.js#L342). Since the type is constant and querying the dataset meta is not optimal, I would store the type as a private member in `initialize()` (after `me.index = ...`).

```
me.index = datasetIndex;
me._type = me.getMeta().type;
```

Then `_defaults()` becomes:
```javascript
return defaults.datasets[this._type] || {};
```

I would return an empty object in case there is no dataset defaults.

Code after:
		// In order to correctly handle data addition/deletion animation (an thus simulate
		// real-time charts), we need to monitor these data modifications and synchronize
		// the internal meta data accordingly.
		if (me._data !== data) {
			if (me._data) {
				// This case happens when the user replaced the data array instance.
				unlistenArrayEvents(me._data, me);
			}

			if (data && Object.isExtensible(data)) {
				listenArrayEvents(data, me);
			}
			me._data = data;
		}

		// Re-sync meta data in case the user replaced the data array or if we missed
		// any updates and so make sure that we handle number of datapoints changing.
		me.resyncElements();
	},

	/**
	 * Returns the merged user-supplied and default dataset-level options
	 * @private
	 */
	_configure: function() {
		var me = this;
		me._config = helpers.merge({}, [
			me.chart.options.datasets[me._type],
			me.getDataset(),
		], {
			merger: function(key, target, source) {
				if (key !== '_meta' && key !== 'data') {
					helpers._merger(key, target, source);
				}
			}
		});
	},

	_update: function(reset) {
		var me = this;
		me._configure();
		me.update(reset);
	},

	update: helpers.noop,

	transition: function(easingValue) {
		var meta = this.getMeta();
		var elements = meta.data || [];
		var ilen = elements.length;
		var i = 0;