From 6cbf64a72c2f4d15a006c629c00f8c230d5b522a Mon Sep 17 00:00:00 2001 From: "Aziz Gazanchiyan (ZIZ)" Date: Fri, 11 Jun 2021 10:08:34 +0200 Subject: [PATCH] fix(Chart): Handle nullish properties from API extendings safely Chart APIs having null/undefined properties should not break the chart construction now Ref #2132 Close #2134 --- AUTHORS.txt | 1 + src/Chart/Chart.ts | 9 ++++++--- test/internals/bb-spec.ts | 26 +++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 82ed6889c..41417f0bb 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -47,3 +47,4 @@ Marc Faber Donald Pipowitch Sung Oh Park Adrian Schmutzler +Aziz Gazanchiyan diff --git a/src/Chart/Chart.ts b/src/Chart/Chart.ts index b5a694579..b907774de 100644 --- a/src/Chart/Chart.ts +++ b/src/Chart/Chart.ts @@ -4,7 +4,7 @@ */ import ChartInternal from "../ChartInternal/ChartInternal"; import {loadConfig} from "../config/config"; -import {extend, isFunction} from "../module/util"; +import {extend, isFunction, notEmpty} from "../module/util"; import apiChart from "./api/chart"; import apiColor from "./api/color"; @@ -89,12 +89,15 @@ export default class Chart { Object.keys(fn).forEach(key => { const isFunc = isFunction(fn[key]); const isChild = target !== argThis; - const hasChild = Object.keys(fn[key]).length > 0; + const isNotNil = notEmpty(fn[key]); + const hasChild = isNotNil && Object.keys(fn[key]).length > 0; if (isFunc && ((!isChild && hasChild) || isChild)) { target[key] = fn[key].bind(argThis); - } else if (!isFunc) { + } else if (isNotNil && !isFunc) { target[key] = {}; + } else { + target[key] = fn[key]; } hasChild && bindThis(fn[key], target[key], argThis); diff --git a/test/internals/bb-spec.ts b/test/internals/bb-spec.ts index 7cf9d79a2..47b0c5f90 100644 --- a/test/internals/bb-spec.ts +++ b/test/internals/bb-spec.ts @@ -8,7 +8,8 @@ import sinon from "sinon"; import bb from "../../src"; import util from "../assets/util"; import CLASS from "../../src/config/classes"; -import {convertInputType} from "../../src/module/util"; +import Chart from "../../src/Chart/Chart"; +import {convertInputType, extend} from "../../src/module/util"; describe("Interface & initialization", () => { let chart; @@ -113,6 +114,29 @@ describe("Interface & initialization", () => { expect(chart.$.chart.classed(bindtoClassName)).to.be.true; }); + + it("should bind correctly with nullish properties", () => { + const options = { + data: { + columns: [["data1", 0]] + } + }; + + class Extended extends Chart { + nullProperty; + voidProperty; + } + + extend(Chart.prototype, { + nullProperty: null, + voidProperty: undefined + }); + + const extendedInstance = new Chart(options); + + expect((extendedInstance as Extended).nullProperty).to.be.null; + expect((extendedInstance as Extended).voidProperty).to.be.undefined; + }); }); describe("auto resize", () => {