]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Resolve to false only when _fallback is used (#8542)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Sun, 28 Feb 2021 22:32:56 +0000 (00:32 +0200)
committerGitHub <noreply@github.com>
Sun, 28 Feb 2021 22:32:56 +0000 (17:32 -0500)
* Resolve to false only when _fallback is used
* Typo
* 2nd part

src/helpers/helpers.config.js
test/specs/core.datasetController.tests.js
test/specs/helpers.config.tests.js

index 7fd5674ada9d736eda0ae5b56a18c74764840ef7..96c0f8c93049024028a1800df6baeb0106925e57 100644 (file)
@@ -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;
index c65510aad1bed47dc1760a2e574d0ff68c93040c..3c37751e081844b03f2b1edd0bf3984763c20b65 100644 (file)
@@ -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({
index e9a22a1377e7c6ee4afdf845bccfd379db16b2c6..48e046a90c2537595a9000b53fdd517d333b8b59 100644 (file)
@@ -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 = {