From 86b189281093c3f7abb6c44e79340e3a58df767f Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Mon, 1 Mar 2021 00:32:56 +0200 Subject: [PATCH] Resolve to false only when _fallback is used (#8542) * Resolve to false only when _fallback is used * Typo * 2nd part --- src/helpers/helpers.config.js | 30 ++++++++++++---------- test/specs/core.datasetController.tests.js | 25 ++++++++++++++++++ test/specs/helpers.config.tests.js | 22 ++++++++++++++++ 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/helpers/helpers.config.js b/src/helpers/helpers.config.js index 7fd5674ad..96c0f8c93 100644 --- a/src/helpers/helpers.config.js +++ b/src/helpers/helpers.config.js @@ -172,7 +172,7 @@ export function _descriptors(proxy, defaults = {scriptable: true, indexable: tru } const readKey = (prefix, name) => prefix ? prefix + _capitalize(name) : name; -const needsSubResolver = (prop, value) => isObject(value); +const needsSubResolver = (prop, value) => isObject(value) && prop !== 'adapters'; function _cached(target, prop, resolve) { let value = target[prop]; // cached value @@ -258,9 +258,9 @@ function addScopes(set, parentScopes, key, parentFallback) { // The fallback will resume to that new scope. return fallback; } - } else if (scope === false && key !== 'fill') { - // Fallback to `false` results to `false`, expect for `fill`. - // The special case (fill) should be handled through descriptors. + } else if (scope === false && defined(parentFallback) && key !== parentFallback) { + // Fallback to `false` results to `false`, when falling back to different key. + // For example `interaction` from `hover` or `plugins.tooltip` and `animation` from `animations` return null; } } @@ -272,23 +272,25 @@ function createSubResolver(parentScopes, resolver, prop, value) { const fallback = resolveFallback(resolver._fallback, prop, value); const allScopes = [...parentScopes, ...rootScopes]; const set = new Set([value]); - let key = prop; - while (key !== false) { - key = addScopes(set, allScopes, key, fallback); - if (key === null) { - return false; - } + let key = addScopesFromKey(set, allScopes, prop, fallback || prop); + if (key === null) { + return false; } if (defined(fallback) && fallback !== prop) { - const fallbackScopes = allScopes; - key = fallback; - while (key !== false) { - key = addScopes(set, fallbackScopes, key, fallback); + key = addScopesFromKey(set, allScopes, fallback, key); + if (key === null) { + return false; } } return _createResolver([...set], [''], rootScopes, fallback); } +function addScopesFromKey(set, allScopes, key, fallback) { + while (key) { + key = addScopes(set, allScopes, key, fallback); + } + return key; +} function _resolveWithPrefixes(prop, prefixes, scopes, proxy) { let value; diff --git a/test/specs/core.datasetController.tests.js b/test/specs/core.datasetController.tests.js index c65510aad..3c37751e0 100644 --- a/test/specs/core.datasetController.tests.js +++ b/test/specs/core.datasetController.tests.js @@ -674,6 +674,31 @@ describe('Chart.DatasetController', function() { Chart.defaults.borderColor = oldColor; }); + it('should read parsing from options when default is false', function() { + const originalDefault = Chart.defaults.parsing; + Chart.defaults.parsing = false; + + var chart = acquireChart({ + type: 'line', + data: { + datasets: [{ + data: [{t: 1, y: 0}] + }] + }, + options: { + parsing: { + xAxisKey: 't' + } + } + }); + + var meta = chart.getDatasetMeta(0); + expect(meta.data[0].x).not.toBeNaN(); + + // Reset old shared state + Chart.defaults.parsing = originalDefault; + }); + describe('resolveDataElementOptions', function() { it('should cache options when possible', function() { const chart = acquireChart({ diff --git a/test/specs/helpers.config.tests.js b/test/specs/helpers.config.tests.js index e9a22a137..48e046a90 100644 --- a/test/specs/helpers.config.tests.js +++ b/test/specs/helpers.config.tests.js @@ -656,6 +656,28 @@ describe('Chart.helpers.config', function() { expect('test' in opts).toBeFalse(); }); + it('should not create proxy for adapters', function() { + const defaults = { + scales: { + time: { + adapters: { + date: { + locale: { + method: (arg) => arg === undefined ? 'ok' : 'fail' + } + } + } + } + } + }; + + const resolver = _createResolver([{}, defaults]); + const opts = _attachContext(resolver, {index: 1}); + const fn = opts.scales.time.adapters.date.locale.method; + expect(typeof fn).toBe('function'); + expect(fn()).toEqual('ok'); + }); + describe('_indexable and _scriptable', function() { it('should default to true', function() { const options = {