From fce827d893b65190d5577a9fb73da516b940e382 Mon Sep 17 00:00:00 2001 From: Mohammad Wasi Date: Sat, 5 Sep 2026 15:12:38 +0530 Subject: [PATCH] fix(model): don't require TimelineComponent for media-only option. close #21686 When an option uses the full `{ baseOption, media }` form without a `timeline`, `OptionManager.parseRawOption` injects an empty `timeline` key into `baseOption` (`baseOption.timeline = timelineOnRoot`, where `timelineOnRoot` is `undefined`). `checkMissingComponents` then iterated that key and wrongly reported `TimelineComponent` as "used but not imported", even though no timeline is configured. Guard `checkMissingComponents` so component options whose value is `null`/`undefined` are not treated as used. Adds a regression test. Co-Authored-By: Claude Opus 4.8 --- src/model/Global.ts | 6 ++++- test/ut/spec/model/componentMissing.test.ts | 29 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/model/Global.ts b/src/model/Global.ts index 32b8b769f9..eb072895de 100644 --- a/src/model/Global.ts +++ b/src/model/Global.ts @@ -141,7 +141,11 @@ const componetsMissingLogPrinted: Record = {}; function checkMissingComponents(option: ECUnitOption) { each(option, function (componentOption, mainType: ComponentMainType) { - if (!ComponentModel.hasClass(mainType)) { + // A `null`/`undefined` option value means the component is not actually + // used and should not be reported as missing. For example, `parseRawOption` + // injects an empty `timeline` entry into `baseOption` when using the + // `{ baseOption, media }` form without a `timeline`. See #21686. + if (componentOption != null && !ComponentModel.hasClass(mainType)) { const componentImportName = BUITIN_COMPONENTS_MAP[mainType as keyof typeof BUITIN_COMPONENTS_MAP]; if (componentImportName && !componetsMissingLogPrinted[componentImportName]) { error(`Component ${mainType} is used but not imported. diff --git a/test/ut/spec/model/componentMissing.test.ts b/test/ut/spec/model/componentMissing.test.ts index bfbe58a810..c7fa87e7c2 100644 --- a/test/ut/spec/model/componentMissing.test.ts +++ b/test/ut/spec/model/componentMissing.test.ts @@ -149,4 +149,33 @@ describe('model_componentMissing', function () { console.error = oldConsoleErr; }); + + it('Should not report timeline component missing error for media-only option without timeline', function () { + // See #21686: when using the full `{ baseOption, media }` form without a + // `timeline`, an empty `timeline` entry was injected into `baseOption`, + // which was wrongly reported as a missing `TimelineComponent`. + const chart = createChart(); + console.error = jest.fn(); + chart.setOption({ + baseOption: { + series: [{ + type: 'pie' + }] + }, + media: [{ + query: { maxWidth: 500 }, + option: { + series: [{ + type: 'pie', + radius: '50%' + }] + } + }] + }); + expect(console.error).not.toHaveBeenCalledWith( + makeComponentError('timeline', 'TimelineComponent') + ); + + console.error = oldConsoleErr; + }); }); \ No newline at end of file