You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2026/03/15 20:09:53 UTC
(echarts) 24/32: fix: (1) Clarify and uniform terminology and add comments to explain EC_CYCLE. (2) Fix dataZoom in `appendData`, introduced by recent commits.
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch PR/plainheart_fix/alignTicks-precision
in repository https://gitbox.apache.org/repos/asf/echarts.git
commit bd19110f247d9221849f43d18f8b49b590095520
Author: 100pah <su...@gmail.com>
AuthorDate: Sun Mar 8 02:51:11 2026 +0800
fix: (1) Clarify and uniform terminology and add comments to explain EC_CYCLE. (2) Fix dataZoom in `appendData`, introduced by recent commits.
---
src/component/dataZoom/dataZoomProcessor.ts | 2 +
src/component/dataZoom/helper.ts | 3 +-
src/component/thumbnail/ThumbnailBridgeImpl.ts | 2 +-
src/component/thumbnail/ThumbnailView.ts | 2 +-
src/coord/axisAlignTicks.ts | 4 +
src/coord/axisStatistics.ts | 19 ++--
src/coord/scaleRawExtentInfo.ts | 12 +-
src/core/ExtensionAPI.ts | 2 +-
src/core/Scheduler.ts | 23 ++--
src/core/echarts.ts | 150 +++++++++++++++++--------
src/core/task.ts | 10 +-
src/label/LabelManager.ts | 2 +-
src/label/labelLayoutHelper.ts | 2 +-
src/model/OptionManager.ts | 6 -
src/scale/scaleMapper.ts | 4 +-
src/util/cycleCache.ts | 73 ++++++++++++
src/util/model.ts | 50 ---------
src/util/types.ts | 57 ++++++++--
test/bar-polar-multi-series-radial.html | 2 +-
19 files changed, 269 insertions(+), 156 deletions(-)
diff --git a/src/component/dataZoom/dataZoomProcessor.ts b/src/component/dataZoom/dataZoomProcessor.ts
index 96033e38d..811b6a264 100644
--- a/src/component/dataZoom/dataZoomProcessor.ts
+++ b/src/component/dataZoom/dataZoomProcessor.ts
@@ -30,6 +30,8 @@ import { AxisBaseModel } from '../../coord/AxisBaseModel';
const dataZoomProcessor: StageHandler = {
+ dirtyOnOverallProgress: true,
+
// `dataZoomProcessor` will only be performed in needed series. Consider if
// there is a line series and a pie series, it is better not to update the
// line series if only pie series is needed to be updated.
diff --git a/src/component/dataZoom/helper.ts b/src/component/dataZoom/helper.ts
index d3170ea2b..9fb7c3b58 100644
--- a/src/component/dataZoom/helper.ts
+++ b/src/component/dataZoom/helper.ts
@@ -25,8 +25,9 @@ import SeriesModel from '../../model/Series';
import { CoordinateSystemHostModel } from '../../coord/CoordinateSystem';
import { AxisBaseModel } from '../../coord/AxisBaseModel';
import type AxisProxy from './AxisProxy';
-import { getCachePerECPrepare, GlobalModelCachePerECPrepare, makeInner } from '../../util/model';
+import { makeInner } from '../../util/model';
import type ComponentModel from '../../model/Component';
+import { getCachePerECPrepare, GlobalModelCachePerECPrepare } from '../../util/cycleCache';
export interface DataZoomPayloadBatchItem {
diff --git a/src/component/thumbnail/ThumbnailBridgeImpl.ts b/src/component/thumbnail/ThumbnailBridgeImpl.ts
index 9b33cec8c..f155613dc 100644
--- a/src/component/thumbnail/ThumbnailBridgeImpl.ts
+++ b/src/component/thumbnail/ThumbnailBridgeImpl.ts
@@ -51,7 +51,7 @@ export class ThumbnailBridgeImpl implements ThumbnailBridge {
}
reset(api: ExtensionAPI) {
- this._renderVersion = api.getMainProcessVersion();
+ this._renderVersion = api.getECMainCycleVersion();
}
renderContent(opt: {
diff --git a/src/component/thumbnail/ThumbnailView.ts b/src/component/thumbnail/ThumbnailView.ts
index 617f6dfda..a08f1470b 100644
--- a/src/component/thumbnail/ThumbnailView.ts
+++ b/src/component/thumbnail/ThumbnailView.ts
@@ -70,7 +70,7 @@ export class ThumbnailView extends ComponentView {
return;
}
- this._renderVersion = api.getMainProcessVersion();
+ this._renderVersion = api.getECMainCycleVersion();
const group = this.group;
group.removeAll();
diff --git a/src/coord/axisAlignTicks.ts b/src/coord/axisAlignTicks.ts
index 0fb54eedd..61f11ed20 100644
--- a/src/coord/axisAlignTicks.ts
+++ b/src/coord/axisAlignTicks.ts
@@ -56,6 +56,10 @@ export function scaleCalcAlign(
targetScale, targetAxisModel, targetAxisModel.ecModel, targetAxis, null
);
+ // FIXME:
+ // (1) Axis inverse is not considered yet.
+ // (2) `SCALE_EXTENT_KIND_MAPPING` is not considered yet.
+
const isTargetLogScale = isLogScale(targetScale);
const alignToScaleLinear = isLogScale(alignToScale) ? alignToScale.intervalStub : alignToScale;
const targetIntervalStub = isTargetLogScale ? targetScale.intervalStub : targetScale;
diff --git a/src/coord/axisStatistics.ts b/src/coord/axisStatistics.ts
index f64ae1faa..ca2454619 100644
--- a/src/coord/axisStatistics.ts
+++ b/src/coord/axisStatistics.ts
@@ -21,8 +21,6 @@ import { assert, createHashMap, each, HashMap } from 'zrender/src/core/util';
import type GlobalModel from '../model/Global';
import type SeriesModel from '../model/Series';
import {
- getCachePerECFullUpdate, getCachePerECPrepare, GlobalModelCachePerECFullUpdate,
- GlobalModelCachePerECPrepare,
initExtentForUnion, makeCallOnlyOnce, makeInner,
} from '../util/model';
import { DimensionIndex, NullUndefined } from '../util/types';
@@ -34,6 +32,10 @@ import type { AxisBaseModel } from './AxisBaseModel';
import { tryEnsureTypedArray, Float64ArrayCtor } from '../util/vendor';
import { EChartsExtensionInstallRegisters } from '../extension';
import type ComponentModel from '../model/Component';
+import {
+ getCachePerECFullUpdate, getCachePerECPrepare, GlobalModelCachePerECFullUpdate,
+ GlobalModelCachePerECPrepare
+} from '../util/cycleCache';
const callOnlyOnce = makeCallOnlyOnce();
@@ -237,7 +239,7 @@ export function eachAxisStatKey(
});
}
-function performAxisStatistics(ecModel: GlobalModel): void {
+function performAxisStatisticsOnOverallReset(ecModel: GlobalModel): void {
const ecFullUpdateCache = ecModelCacheFullUpdateInner(getCachePerECFullUpdate(ecModel));
const axisStatAll: AxisStatAll = ecFullUpdateCache.all = createHashMap();
@@ -350,11 +352,10 @@ function performStatisticsForRecord(
}
if (!ecPrepareCacheMiss && ecPrepareLiPosMinGap != null) {
// Consider the fact in practice:
- // - Series data can only be changed in the "ec prepare" stage.
- // - The relationship between series and axes can only be changed in "ec prepare" stage and
- // `SERIES_FILTER`.
- // (NOTE: "ec prepare" stage can be typically considered as `chart.setOption`, and "ec updated"
- // stage can be typically considered as `dispatchAction`.)
+ // - Series data can only be changed in EC_PREPARE_UPDATE.
+ // - The relationship between series and axes can only be changed in EC_PREPARE_UPDATE and
+ // SERIES_FILTER.
+ // (See EC_CYCLE for more info)
// Therefore, some statistics results can be cached in `GlobalModelCachePerECPrepare` to avoid
// repeated time-consuming calculation for large data (e.g., over 1e5 data items).
perKeyPerAxis.liPosMinGap = ecPrepareLiPosMinGap;
@@ -452,7 +453,7 @@ export function requireAxisStatistics(
callOnlyOnce(registers, function () {
registers.registerProcessor(registers.PRIORITY.PROCESSOR.AXIS_STATISTICS, {
- overallReset: performAxisStatistics
+ overallReset: performAxisStatisticsOnOverallReset
});
});
}
diff --git a/src/coord/scaleRawExtentInfo.ts b/src/coord/scaleRawExtentInfo.ts
index d9d7ed6b4..f378b5da5 100644
--- a/src/coord/scaleRawExtentInfo.ts
+++ b/src/coord/scaleRawExtentInfo.ts
@@ -58,7 +58,7 @@ import { AxisStatKey, eachAxisStatKey } from './axisStatistics';
*/
const scaleInner = makeInner<{
extent: number[];
- // series on this axis.
+ // series on this axis to union data extent.
seriesList: SeriesModel[];
dimIdxInCoord: number;
}, Scale>();
@@ -422,9 +422,6 @@ export class ScaleRawExtentInfo {
* The outcome `_zoomMM` may have both `NullUndefined` and a finite value, like `[undefined, 123]`.
*/
setZoomMinMax(idxMinMax: 0 | 1, val: number | NullUndefined): void {
- if (__DEV__) {
- assert(this._i.zoomMM[idxMinMax] == null);
- }
this._i.zoomMM[idxMinMax] = val;
}
@@ -596,8 +593,11 @@ export function scaleRawExtentInfoReallyCreate(
if (scale.rawExtentInfo) {
if (__DEV__) {
// Check for incorrect impl - the duplicated calling of this method is only allowed in
- // one case: first dataZoom then coord sys update.
- assert(scale.rawExtentInfo.from !== from);
+ // these cases:
+ // - First in `AxisProxy['reset']` (for dataZoom)
+ // - Then in `CoordinateSystem['update']`.
+ // - Then after `chart.appendData()` due to `dirtyOnOverallProgress: true`
+ assert(scale.rawExtentInfo.from !== from || from === AXIS_EXTENT_INFO_BUILD_FROM_DATA_ZOOM);
}
return;
}
diff --git a/src/core/ExtensionAPI.ts b/src/core/ExtensionAPI.ts
index 047bb704c..cfba0a270 100644
--- a/src/core/ExtensionAPI.ts
+++ b/src/core/ExtensionAPI.ts
@@ -72,7 +72,7 @@ abstract class ExtensionAPI {
abstract getViewOfComponentModel(componentModel: ComponentModel): ComponentView;
abstract getViewOfSeriesModel(seriesModel: SeriesModel): ChartView;
abstract getModel(): GlobalModel;
- abstract getMainProcessVersion(): number;
+ abstract getECMainCycleVersion(): number;
}
export default ExtensionAPI;
diff --git a/src/core/Scheduler.ts b/src/core/Scheduler.ts
index 745631111..c87690e95 100644
--- a/src/core/Scheduler.ts
+++ b/src/core/Scheduler.ts
@@ -68,6 +68,8 @@ type TaskRecord = {
overallTask?: OverallTask
};
type PerformStageTaskOpt = {
+ // `block` means running from the beginning to the final end within
+ // an individual "progress".
block?: boolean,
setDirty?: boolean,
visualType?: StageHandlerInternal['visualType'],
@@ -96,7 +98,7 @@ interface OverallTaskContext extends TaskContext {
}
interface StubTaskContext extends TaskContext {
model: SeriesModel;
- overallProgress: boolean;
+ dirtyOnOverallProgress: boolean;
};
class Scheduler {
@@ -147,7 +149,7 @@ class Scheduler {
// if a data processor depends on a component (e.g., dataZoomProcessor depends
// on the settings of `dataZoom`), it should be re-performed if the component
// is modified by `setOption`.
- // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,
+ // (2) If a processor depends on several series, specified by its `getTargetSeries`,
// it should be re-performed when the result array of `getTargetSeries` changed.
// We use `dependencies` to cover these issues.
// (3) How to update target series when coordinate system related components modified.
@@ -488,15 +490,13 @@ class Scheduler {
const seriesType = stageHandler.seriesType;
const getTargetSeries = stageHandler.getTargetSeries;
- let overallProgress = true;
+ const dirtyOnOverallProgress = stageHandler.dirtyOnOverallProgress;
let shouldOverallTaskDirty = false;
// FIXME:TS never used, so comment it
// let modifyOutputEnd = stageHandler.modifyOutputEnd;
// An overall task with seriesType detected or has `getTargetSeries`, we add
- // stub in each pipelines, it will set the overall task dirty when the pipeline
- // progress. Moreover, to avoid call the overall task each frame (too frequent),
- // we set the pipeline block.
+ // stub in each pipelines to receive dirty info from upstream.
let errMsg = '';
if (__DEV__) {
errMsg = '"createOnAllSeries" is not supported for "overallReset", '
@@ -509,12 +509,7 @@ class Scheduler {
else if (getTargetSeries) {
getTargetSeries(ecModel, api).each(createStub);
}
- // Otherwise, (usually it is legacy case), the overall task will only be
- // executed when upstream is dirty. Otherwise the progressive rendering of all
- // pipelines will be disabled unexpectedly. But it still needs stubs to receive
- // dirty info from upstream.
else {
- overallProgress = false;
each(ecModel.getSeries(), createStub);
}
@@ -534,12 +529,12 @@ class Scheduler {
);
stub.context = {
model: seriesModel,
- overallProgress: overallProgress
+ dirtyOnOverallProgress: dirtyOnOverallProgress
// FIXME:TS never used, so comment it
// modifyOutputEnd: modifyOutputEnd
};
stub.agent = overallTask;
- stub.__block = overallProgress;
+ stub.__block = dirtyOnOverallProgress;
scheduler._pipe(seriesModel, stub);
}
@@ -586,7 +581,7 @@ function overallTaskReset(context: OverallTaskContext): void {
}
function stubReset(context: StubTaskContext): TaskProgressCallback<StubTaskContext> {
- return context.overallProgress && stubProgress;
+ return context.dirtyOnOverallProgress && stubProgress;
}
function stubProgress(this: StubTask): void {
diff --git a/src/core/echarts.ts b/src/core/echarts.ts
index dc350f92c..ad5bb2bdc 100644
--- a/src/core/echarts.ts
+++ b/src/core/echarts.ts
@@ -139,6 +139,7 @@ import type geoSourceManager from '../coord/geo/geoSourceManager';
import {
registerCustomSeries as registerCustom
} from '../chart/custom/customSeriesRegister';
+import { resetCachePerECFullUpdate, resetCachePerECPrepare } from '../util/cycleCache';
declare let global: any;
@@ -203,17 +204,68 @@ export const PRIORITY = {
}
};
-// Main process have three entries: `setOption`, `dispatchAction` and `resize`,
-// where they must not be invoked nestedly, except the only case: invoke
-// dispatchAction with updateMethod "none" in main process.
-// This flag is used to carry out this rule.
-// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
-const IN_MAIN_PROCESS_KEY = '__flagInMainProcess' as const;
+/**
+ * [ec updating/rendering cycles (EC_CYCLE)]
+ *
+ * - EC_MAIN_CYCLE:
+ * - It designates a run of a series of processing/updating/rendering.
+ * - It is triggered by:
+ * - `setOption`
+ * - `dispatchAction`
+ * (It is typically internally triggered by user inputs; but can also an explicit API call.)
+ * - `resize`
+ * - The next "animation frame" if in `lazyMode: true`.
+ * - Nested entry is not allowed. If triggering a new run of EC_MAIN_CYCLE during a
+ * unfinished run, the new run will be delayed until the current run finishes
+ * (if triggered by `dispatchAction`), or throw error (if triggered by other API calls).
+ * - All user-visible ec events are triggered outside EC_MAIN_CYCLE
+ * (i.e. be triggered after `this[IN_EC_MAIN_CYCLE_KEY]` becoming `false`).
+ * - A run of EC_MAIN_CYCLE comprises:
+ * - EC_PREPARE_UPDATE (may be absent)
+ * - EC_FULL_UPDATE or EC_PARTIAL_UPDATE
+ * - A run of EC_FULL_UPDATE comprises:
+ * - CoordinateSystem['create']
+ * - Data processing (may be absent) (see `registerProcessor`)
+ * - CoordinateSystem['update'] (may be absent)
+ * - Visual encoding (may be absent) (see `registerVisual`)
+ * - Layout (may be absent) (see `registerLayout`)
+ * - Rendering (`ComponentView` or `SeriesView`)
+ *
+ * - EC_PROGRESSIVE_CYCLE:
+ * - It also carries out a series of processing/updating/rendering, but out of EC_MAIN_CYCLE.
+ * - It is performed in each "animation frame".
+ * - It can be triggered internally or `appendData` call.
+ * - A run of EC_PROGRESSIVE_CYCLE comprises:
+ * - Data processing (may be absent) (see `registerProcessor`)
+ * - Visual encoding (may be absent) (see `registerVisual`)
+ * - Layout (may be absent) (see `registerLayout`)
+ * - Rendering (`ComponentView` or `SeriesView`)
+ * - PENDING: currently all data processing tasks (via `registerProcessor`) run in "block" mode.
+ * (see `performDataProcessorTasks`)
+ *
+ * - Other updating/rendering cycles:
+ * - Some series have specific update/render cycles. For example, graph force layout performs
+ * layout and rendering in each "animation frame".
+ *
+ * - Model updating:
+ * - Model can only be modified at the beginning of ec cycles, including only:
+ * - EC_PREPARE_UPDATE (see method `prepare()`) in `setOption` call.
+ * - EC action handlers in `dispatchAction` call.
+ * - `appendData` (a special case, where only data is modified).
+ *
+ * - The lifetime of CoordinateSystem/Axis/Scale instances:
+ * - They are only re-created per run of EC_FULL_UPDATE.
+ *
+ * - Available caches: see `cycleCache.ts`
+ */
+
+// See comments in EC_CYCLE.
+const IN_EC_MAIN_CYCLE_KEY = '__flagInMainProcess' as const;
// Useful for detecting outdated rendering results in scenarios that these issues are involved:
-// - Use shortcut (such as, updateTransform, or no update) to start a main process.
+// - Use EC_PARTIAL_UPDATE (such as, updateTransform, or no update) to start an EC_MAIN_CYCLE.
// - Asynchronously update rendered view (e.g., graph force layout).
// - Multiple ChartView/ComponentView render to one group cooperatively.
-const MAIN_PROCESS_VERSION_KEY = '__mainProcessVersion' as const;
+const EC_MAIN_CYCLE_VERSION_KEY = '__mainProcessVersion' as const;
const PENDING_UPDATE = '__pendingUpdate' as const;
const STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus' as const;
const ACTION_REG = /^[a-zA-Z0-9_]+$/;
@@ -285,7 +337,7 @@ messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off');
// ---------------------------------------
// Internal method names for class ECharts
// ---------------------------------------
-let prepare: (ecIns: ECharts) => void;
+let prepare: (ecIns: ECharts) => void; // This is `EC_PREPARE_UPDATE`.
let prepareView: (ecIns: ECharts, isComponent: boolean) => void;
let updateDirectly: (
ecIns: ECharts, method: string, payload: Payload, mainType: ComponentMainType, subType?: ComponentSubType
@@ -293,11 +345,11 @@ let updateDirectly: (
type UpdateMethod = (this: ECharts, payload?: Payload, renderParams?: UpdateLifecycleParams) => void;
let updateMethods: {
prepareAndUpdate: UpdateMethod,
- update: UpdateMethod,
- updateTransform: UpdateMethod,
- updateView: UpdateMethod,
- updateVisual: UpdateMethod,
- updateLayout: UpdateMethod
+ update: UpdateMethod, // This is `EC_FULL_UPDATE`.
+ updateTransform: UpdateMethod, // This is one of `EC_PARTIAL_UPDATE`.
+ updateView: UpdateMethod, // This is one of `EC_PARTIAL_UPDATE`.
+ updateVisual: UpdateMethod, // This is one of `EC_PARTIAL_UPDATE`.
+ updateLayout: UpdateMethod // This is one of `EC_PARTIAL_UPDATE`.
};
let doConvertPixel: {
(
@@ -345,7 +397,7 @@ let enableConnect: (ecIns: ECharts) => void;
let markStatusToUpdate: (ecIns: ECharts) => void;
let applyChangedStates: (ecIns: ECharts) => void;
-let updateMainProcessVersion: (ecIns: ECharts) => void;
+let updateECMainCycleVersion: (ecIns: ECharts) => void;
type RenderedEventParam = { elapsedTime: number };
type ECEventDefinition = {
@@ -427,8 +479,8 @@ class ECharts extends Eventful<ECEventDefinition> {
silent: boolean
updateParams: UpdateLifecycleParams
};
- private [IN_MAIN_PROCESS_KEY]: boolean;
- private [MAIN_PROCESS_VERSION_KEY]: number;
+ private [IN_EC_MAIN_CYCLE_KEY]: boolean;
+ private [EC_MAIN_CYCLE_VERSION_KEY]: number;
private [CONNECT_STATUS_KEY]: ConnectStatus;
private [STATUS_NEEDS_UPDATE_KEY]: boolean;
@@ -451,7 +503,7 @@ class ECharts extends Eventful<ECEventDefinition> {
let defaultCoarsePointer: 'auto' | boolean = 'auto';
let defaultUseDirtyRect = false;
- this[MAIN_PROCESS_VERSION_KEY] = 1;
+ this[EC_MAIN_CYCLE_VERSION_KEY] = 1;
if (__DEV__) {
const root = (
@@ -545,15 +597,15 @@ class ECharts extends Eventful<ECEventDefinition> {
if (this[PENDING_UPDATE]) {
const silent = (this[PENDING_UPDATE] as any).silent;
- this[IN_MAIN_PROCESS_KEY] = true;
- updateMainProcessVersion(this);
+ this[IN_EC_MAIN_CYCLE_KEY] = true;
+ updateECMainCycleVersion(this);
try {
prepare(this);
updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams);
}
catch (e) {
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
this[PENDING_UPDATE] = null;
throw e;
}
@@ -566,7 +618,7 @@ class ECharts extends Eventful<ECEventDefinition> {
// will render the final state of the elements before the real animation started.
this._zr.flush();
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
this[PENDING_UPDATE] = null;
flushPendingActions.call(this, silent);
@@ -649,7 +701,7 @@ class ECharts extends Eventful<ECEventDefinition> {
setOption<Opt extends ECBasicOption>(option: Opt, opts?: SetOptionOpts): void;
/* eslint-disable-next-line */
setOption<Opt extends ECBasicOption>(option: Opt, notMerge?: boolean | SetOptionOpts, lazyUpdate?: boolean): void {
- if (this[IN_MAIN_PROCESS_KEY]) {
+ if (this[IN_EC_MAIN_CYCLE_KEY]) {
if (__DEV__) {
error('`setOption` should not be called during main process.');
}
@@ -672,8 +724,8 @@ class ECharts extends Eventful<ECEventDefinition> {
notMerge = notMerge.notMerge;
}
- this[IN_MAIN_PROCESS_KEY] = true;
- updateMainProcessVersion(this);
+ this[IN_EC_MAIN_CYCLE_KEY] = true;
+ updateECMainCycleVersion(this);
if (!this._model || notMerge) {
const optionManager = new OptionManager(this._api);
@@ -696,7 +748,7 @@ class ECharts extends Eventful<ECEventDefinition> {
silent: silent,
updateParams: updateParams
};
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
// `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
// It should wake it up to make sure zrender start to render at the next frame.
@@ -709,7 +761,7 @@ class ECharts extends Eventful<ECEventDefinition> {
}
catch (e) {
this[PENDING_UPDATE] = null;
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
throw e;
}
@@ -722,7 +774,7 @@ class ECharts extends Eventful<ECEventDefinition> {
}
this[PENDING_UPDATE] = null;
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
flushPendingActions.call(this, silent);
triggerUpdatedEvent.call(this, silent);
@@ -735,7 +787,7 @@ class ECharts extends Eventful<ECEventDefinition> {
* @param opts Optional settings
*/
setTheme(theme: string | ThemeOption, opts?: SetThemeOpts): void {
- if (this[IN_MAIN_PROCESS_KEY]) {
+ if (this[IN_EC_MAIN_CYCLE_KEY]) {
if (__DEV__) {
error('`setTheme` should not be called during main process.');
}
@@ -763,8 +815,8 @@ class ECharts extends Eventful<ECEventDefinition> {
this[PENDING_UPDATE] = null;
}
- this[IN_MAIN_PROCESS_KEY] = true;
- updateMainProcessVersion(this);
+ this[IN_EC_MAIN_CYCLE_KEY] = true;
+ updateECMainCycleVersion(this);
try {
this._updateTheme(theme);
@@ -774,11 +826,11 @@ class ECharts extends Eventful<ECEventDefinition> {
updateMethods.update.call(this, {type: 'setTheme'}, updateParams);
}
catch (e) {
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
throw e;
}
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
flushPendingActions.call(this, silent);
triggerUpdatedEvent.call(this, silent);
@@ -1357,7 +1409,7 @@ class ECharts extends Eventful<ECEventDefinition> {
* Resize the chart
*/
resize(opts?: ResizeOpts): void {
- if (this[IN_MAIN_PROCESS_KEY]) {
+ if (this[IN_EC_MAIN_CYCLE_KEY]) {
if (__DEV__) {
error('`resize` should not be called during main process.');
}
@@ -1395,8 +1447,8 @@ class ECharts extends Eventful<ECEventDefinition> {
this[PENDING_UPDATE] = null;
}
- this[IN_MAIN_PROCESS_KEY] = true;
- updateMainProcessVersion(this);
+ this[IN_EC_MAIN_CYCLE_KEY] = true;
+ updateECMainCycleVersion(this);
try {
needPrepare && prepare(this);
@@ -1409,11 +1461,11 @@ class ECharts extends Eventful<ECEventDefinition> {
});
}
catch (e) {
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
throw e;
}
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
flushPendingActions.call(this, silent);
@@ -1507,7 +1559,7 @@ class ECharts extends Eventful<ECEventDefinition> {
}
// May dispatchAction in rendering procedure
- if (this[IN_MAIN_PROCESS_KEY]) {
+ if (this[IN_EC_MAIN_CYCLE_KEY]) {
this._pendingActions.push(payload);
return;
}
@@ -1579,7 +1631,7 @@ class ECharts extends Eventful<ECEventDefinition> {
private static internalField = (function () {
prepare = function (ecIns: ECharts): void {
- modelUtil.resetCachePerECPrepare(ecIns._model);
+ resetCachePerECPrepare(ecIns._model);
const scheduler = ecIns._scheduler;
@@ -1806,7 +1858,7 @@ class ECharts extends Eventful<ECEventDefinition> {
return;
}
- modelUtil.resetCachePerECFullUpdate(ecModel);
+ resetCachePerECFullUpdate(ecModel);
ecModel.setUpdatePayload(payload);
scheduler.restoreData(ecModel, payload);
@@ -2050,8 +2102,8 @@ class ECharts extends Eventful<ECEventDefinition> {
const updateMethod = cptTypeTmp.pop();
const cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);
- this[IN_MAIN_PROCESS_KEY] = true;
- updateMainProcessVersion(this);
+ this[IN_EC_MAIN_CYCLE_KEY] = true;
+ updateECMainCycleVersion(this);
let payloads: Payload[] = [payload];
let batched = false;
@@ -2122,7 +2174,7 @@ class ECharts extends Eventful<ECEventDefinition> {
}
}
catch (e) {
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
throw e;
}
}
@@ -2139,7 +2191,7 @@ class ECharts extends Eventful<ECEventDefinition> {
eventObj = eventObjBatch[0] as ECActionEvent;
}
- this[IN_MAIN_PROCESS_KEY] = false;
+ this[IN_EC_MAIN_CYCLE_KEY] = false;
if (!silent) {
let refinedEvent: ECActionEvent;
@@ -2434,8 +2486,8 @@ class ECharts extends Eventful<ECEventDefinition> {
ecIns.getZr().wakeUp();
};
- updateMainProcessVersion = function (ecIns: ECharts): void {
- ecIns[MAIN_PROCESS_VERSION_KEY] = (ecIns[MAIN_PROCESS_VERSION_KEY] + 1) % 1000;
+ updateECMainCycleVersion = function (ecIns: ECharts): void {
+ ecIns[EC_MAIN_CYCLE_VERSION_KEY] = (ecIns[EC_MAIN_CYCLE_VERSION_KEY] + 1) % 1000;
};
applyChangedStates = function (ecIns: ECharts): void {
@@ -2666,8 +2718,8 @@ class ECharts extends Eventful<ECEventDefinition> {
getViewOfSeriesModel(seriesModel: SeriesModel): ChartView {
return ecIns.getViewOfSeriesModel(seriesModel);
}
- getMainProcessVersion(): number {
- return ecIns[MAIN_PROCESS_VERSION_KEY];
+ getECMainCycleVersion(): number {
+ return ecIns[EC_MAIN_CYCLE_VERSION_KEY];
}
})(ecIns);
};
diff --git a/src/core/task.ts b/src/core/task.ts
index 6a25c1c12..20a59d3fb 100644
--- a/src/core/task.ts
+++ b/src/core/task.ts
@@ -112,7 +112,7 @@ export class Task<Ctx extends TaskContext> {
// Injected in schedular
__pipeline: Pipeline;
__idxInPipeline: number;
- __block: boolean;
+ __block: boolean; // FIXME: simplify it - merge with PerformStageTaskOpt['block']?
// Context must be specified implicitly, to
// avoid miss update context when model changed.
@@ -242,6 +242,14 @@ export class Task<Ctx extends TaskContext> {
return this.unfinished();
}
+ /**
+ * Generally, task dirty propagates to downstream tasks.
+ * Task dirty leads to the `reset` call, which discards the previous result and starts over
+ * the processing.
+ *
+ * See `StageHandler['reset']` and `StageHandler['overallReset']` for a summary of possible
+ * `dirty()` calls.
+ */
dirty(): void {
this._dirty = true;
this._onDirty && this._onDirty(this.context);
diff --git a/src/label/LabelManager.ts b/src/label/LabelManager.ts
index b60a9ac2b..411af3081 100644
--- a/src/label/LabelManager.ts
+++ b/src/label/LabelManager.ts
@@ -86,7 +86,7 @@ interface LabelDesc {
* Save the original value determined in a pass of echarts main process. That refers to the values
* rendered by `SeriesView`, before `series:layoutlabels` is triggered in `renderSeries`.
*
- * 'series:layoutlabels' may be triggered during some shortcut passes, such as zooming in series.graph/geo
+ * 'series:layoutlabels' may be triggered during some EC_PARTIAL_UPDATE passes, such as zooming in series.graph/geo
* (`updateLabelLayout`), where the modified `Element` props should be restorable by the original value here.
*
* Regarding `Element` state, simply consider the values here as the normal state values.
diff --git a/src/label/labelLayoutHelper.ts b/src/label/labelLayoutHelper.ts
index 1136bb63d..856781118 100644
--- a/src/label/labelLayoutHelper.ts
+++ b/src/label/labelLayoutHelper.ts
@@ -509,7 +509,7 @@ export function restoreIgnore(labelList: LabelLayoutData[]): void {
/**
* [NOTICE - restore]:
- * 'series:layoutlabels' may be triggered during some shortcut passes, such as zooming in series.graph/geo
+ * 'series:layoutlabels' may be triggered during some EC_PARTIAL_UPDATE passes, such as zooming in series.graph/geo
* (`updateLabelLayout`), where the modified `Element` props should be restorable from `defaultAttr`.
* @see `SavedLabelAttr` in `LabelManager.ts`
* `restoreIgnore` can be called to perform the restore, if needed.
diff --git a/src/model/OptionManager.ts b/src/model/OptionManager.ts
index ef795ba58..846d3c215 100644
--- a/src/model/OptionManager.ts
+++ b/src/model/OptionManager.ts
@@ -17,12 +17,6 @@
* under the License.
*/
-/**
- * ECharts option manager
- */
-
-
-// import ComponentModel, { ComponentModelConstructor } from './Component';
import ExtensionAPI from '../core/ExtensionAPI';
import {
OptionPreprocessor, MediaQuery, ECUnitOption, MediaUnit, ECBasicOption, SeriesOption
diff --git a/src/scale/scaleMapper.ts b/src/scale/scaleMapper.ts
index 76dd2e871..845594430 100644
--- a/src/scale/scaleMapper.ts
+++ b/src/scale/scaleMapper.ts
@@ -205,7 +205,7 @@ export interface ScaleMapperGeneric<This> {
/**
* [NOTICE]:
- * In ec workflow, scale extent is finally determined at `coordSys#update` stage.
+ * In EC_MAIN_CYCLE, scale extent is finally determined at `coordSys#update` stage.
*
* Get a clone of the scale extent.
* An extent is always in an increase order.
@@ -230,7 +230,7 @@ export interface ScaleMapperGeneric<This> {
*
* `setExtent` is identical to `setExtent2(SCALE_EXTENT_KIND_EFFECTIVE)`.
*
- * [The steps of extent construction in ec workflow]:
+ * [The steps of extent construction in EC_MAIN_CYCLE]:
* - step#1. At `CoordinateSystem#create` stage, requirements of collecting series data extents are
* committed to `scaleRawExtentInfoRequireCreate`, and `Scale` instances are created.
* - step#2. Call `scaleRawExtentInfoReallyCreate` to really collect series data extent and create
diff --git a/src/util/cycleCache.ts b/src/util/cycleCache.ts
new file mode 100644
index 000000000..7d653bb72
--- /dev/null
+++ b/src/util/cycleCache.ts
@@ -0,0 +1,73 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import GlobalModel from '../model/Global';
+import { makeInner } from './model';
+
+
+const ecModelCacheInner = makeInner<{
+ fullUpdate: GlobalModelCachePerECFullUpdate;
+ prepare: GlobalModelCachePerECPrepare;
+}, GlobalModel>();
+
+export type GlobalModelCachePerECPrepare = {__: 'prepare'}; // Nominal to distinguish.
+export type GlobalModelCachePerECFullUpdate = {__: 'fullUpdate'}; // Nominal to distinguish.
+
+/**
+ * CAVEAT: Can only be called by `echarts.ts`
+ */
+export function resetCachePerECPrepare(ecModel: GlobalModel): void {
+ ecModelCacheInner(ecModel).prepare = {} as GlobalModelCachePerECPrepare;
+}
+
+/**
+ * CAVEAT: Can only be called by `echarts.ts`
+ */
+export function resetCachePerECFullUpdate(ecModel: GlobalModel): void {
+ ecModelCacheInner(ecModel).fullUpdate = {} as GlobalModelCachePerECFullUpdate;
+}
+
+/**
+ * The cache is auto cleared at the beginning of EC_PREPARE_UPDATE.
+ * See also comments in EC_CYCLE.
+ *
+ * NOTICE:
+ * - EC_PREPARE_UPDATE is not necessarily executed before each EC_FULL_UPDATE performing.
+ * Typically, `setOption` trigger EC_PREPARE_UPDATE, but `dispatchAction` does not.
+ * - It is not cleared in EC_PARTIAL_UPDATE and EC_PROGRESSIVE_CYCLE.
+ *
+ */
+export function getCachePerECPrepare(ecModel: GlobalModel): GlobalModelCachePerECPrepare {
+ return ecModelCacheInner(ecModel).prepare;
+}
+
+/**
+ * The cache is auto cleared at the beginning of EC_FULL_UPDATE.
+ * See also comments in EC_CYCLE.
+ *
+ * NOTICE:
+ * - It is not cleared in EC_PARTIAL_UPDATE and EC_PROGRESSIVE_CYCLE.
+ * - The cache should NOT be written before EC_FULL_UPDATE started, such as:
+ * - should NOT in `getTargetSeries` methods of data processors.
+ * - should NOT in `init`/`mergeOption`/`optionUpdated`/`getData` methods of component/series models.
+ * - See `getCachePerECPrepare` for details.
+ */
+export function getCachePerECFullUpdate(ecModel: GlobalModel): GlobalModelCachePerECFullUpdate {
+ return ecModelCacheInner(ecModel).fullUpdate;
+}
diff --git a/src/util/model.ts b/src/util/model.ts
index 5412ee058..95d7df3d6 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -30,7 +30,6 @@ import {
isStringSafe,
isNumber,
hasOwn,
- isTypedArray,
} from 'zrender/src/core/util';
import env from 'zrender/src/core/env';
import GlobalModel from '../model/Global';
@@ -1274,55 +1273,6 @@ export function makeCallOnlyOnce<Host extends object>() {
let onceUniqueIndex = getRandomIdBase();
-const ecModelCacheInner = makeInner<{
- fullUpdate: GlobalModelCachePerECFullUpdate;
- prepare: GlobalModelCachePerECPrepare;
-}, GlobalModel>();
-
-export type GlobalModelCachePerECPrepare = {__: 'prepare'}; // Nominal to distinguish.
-export type GlobalModelCachePerECFullUpdate = {__: 'fullUpdate'}; // Nominal to distinguish.
-
-/**
- * CAVEAT: Can only be called by `echarts.ts`
- */
-export function resetCachePerECPrepare(ecModel: GlobalModel): void {
- ecModelCacheInner(ecModel).prepare = {} as GlobalModelCachePerECPrepare;
-}
-
-/**
- * CAVEAT: Can only be called by `echarts.ts`
- */
-export function resetCachePerECFullUpdate(ecModel: GlobalModel): void {
- ecModelCacheInner(ecModel).fullUpdate = {} as GlobalModelCachePerECFullUpdate;
-}
-
-/**
- * The cache is auto cleared at the begining of a run of "ec prepare".
- * Typically, `setOption` trigger "ec prepare", but `dispatchAction` does not.
- *
- * NOTICE:
- * - "ec prepare" is not necessarily performed before each "ec full update" performing.
- */
-export function getCachePerECPrepare(ecModel: GlobalModel): GlobalModelCachePerECPrepare {
- return ecModelCacheInner(ecModel).prepare;
-}
-
-/**
- * The cache is auto cleared at the begining of a run of "ec full update".
- * However, all shortcuts (such as `updateView`/`updateLayout`/etc.) do not clear it.
- * Typically, all `setOption` and some `dispatchAction` trigger "ec full update".
- * This is the same as the lifecycle of coordinate systems instances and axes instances.
- *
- * NOTICE:
- * - The cache should NOT be written in:
- * - `getTargetSeries` methods of data processors.
- * - `init`/`mergeOption`/`optionUpdated`/`getData` methods of component/series models.
- * See `getCachePerECPrepare` for details.
- */
-export function getCachePerECFullUpdate(ecModel: GlobalModel): GlobalModelCachePerECFullUpdate {
- return ecModelCacheInner(ecModel).fullUpdate;
-}
-
/**
* @usage
* - The earlier item takes precedence for duplicate items.
diff --git a/src/util/types.ts b/src/util/types.ts
index ad6e962ad..aebc93ce6 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -336,19 +336,25 @@ export interface StageHandlerOverallReset {
(ecModel: GlobalModel, api: ExtensionAPI, payload?: Payload): void
}
export interface StageHandler {
+
/**
- * Indicate that the task will be piped all series
- * (`performRawSeries` indicate whether includes filtered series).
+ * Indicate that the "series stage task" will be piped for all series
+ * (filtered series is included iff `performRawSeries: true`).
+ *
+ * OVERALL_STAGE_TASK (See `overallReset`) can not set `createOnAllSeries: true`.
*/
createOnAllSeries?: boolean;
+
/**
- * Indicate that the task will be only piped in the pipeline of this type of series.
- * (`performRawSeries` indicate whether includes filtered series).
+ * Indicate that the task will only be piped in the pipeline of this type of series.
+ * (filtered series is included iff `performRawSeries: true`).
+ * It is available for both `reset` and `overallReset`.
*/
seriesType?: string;
+
/**
- * Indicate that the task will be only piped in the pipeline of the returned series.
- * Called in "prepare" stage, before coord sys creation.
+ * Indicate that the task will only be piped in the pipeline of the returned series.
+ * It is called in EC_PREPARE_UPDATE, before `CoordinateSystem['create']`.
* It is available for both `reset` and `overallReset`.
*/
getTargetSeries?: (ecModel: GlobalModel, api: ExtensionAPI) => HashMap<SeriesModel>;
@@ -362,18 +368,45 @@ export interface StageHandler {
* Called only when this task in a pipeline.
*/
plan?: StageHandlerPlan;
+
/**
- * If `overallReset` specified, an "overall task" will be created.
- * "overall task" does not belong to a certain pipeline.
- * They always be "performed" in certain phase (depends on when they declared).
- * They has "stub"s to connect with pipelines (one stub for one pipeline),
- * delivering info like "dirty" and "output end".
+ * If `overallReset` is specified, an OVERALL_STAGE_TASK will be created.
+ * An OVERALL_STAGE_TASK resides across multiple pipelines, and is associated with
+ * pipelines by "stub"s, which deliver messages like "dirty" and "output end".
+ * OVERALL_STAGE_TASK does not support `progess` method.
+ *
+ * The `overallReset` method is called iff this task is "dirty" (See `Task['dirty']`).
+ * See `StageHandler['reset']` for a summary of possible `dirty()` calls.
*/
overallReset?: StageHandlerOverallReset;
+
/**
- * Called only when this task in a single pipeline, and "dirty".
+ * If `reset` is specified, a SERIES_STAGE_TASK will be created.
+ * A SERIES_STAGE_TASK is owned by a pipeline and is specific to a single series.
+ *
+ * The `reset` method is called iff this task is "dirty" (See `Task['dirty']`).
+ * Task `dirty()` call typically originates from:
+ * - A trigger of EC_MAIN_CYCLE (including EC_FULL_UPDATE and EC_PARTIAL_UPDATE)
+ * (See comments in EC_CYCLE)
+ * - NOTICE: `dirtyOnOverallProgress: true` cause that the corresponding `overallReset`
+ * and `reset` of downsteams tasks may also be called in EC_PROGRESSIVE_CYCLE.
+ * But in this case, `CoordinateSystem#create` and `CoordinateSystem#update` are
+ * not called.
*/
reset?: StageHandlerReset;
+
+ /**
+ * This is a temporary mechanism for dataZoom case in `appendData`.
+ *
+ * It will set the OVERALL_STAGE_TASK dirty when the pipeline progress.
+ * Moreover, to avoid call the OVERALL_STAGE_TASK each frame (too frequent),
+ * it set the pipeline block (via `task.__block`) in this stage.
+ *
+ * Otherwise, (usually it is legacy case), the OVERALL_STAGE_TASK will only be
+ * executed when upstream is dirty. Otherwise the progressive rendering of all
+ * pipelines will be disabled unexpectedly.
+ */
+ dirtyOnOverallProgress?: boolean;
}
export interface StageHandlerInternal extends StageHandler {
diff --git a/test/bar-polar-multi-series-radial.html b/test/bar-polar-multi-series-radial.html
index 5185b2551..73374c2a5 100644
--- a/test/bar-polar-multi-series-radial.html
+++ b/test/bar-polar-multi-series-radial.html
@@ -34,7 +34,7 @@ under the License.
</style>
- <!-- <div id="main_multiple_bar_category_angle_axis"></div> -->
+ <div id="main_multiple_bar_category_angle_axis"></div>
<div id="main_multiple_bar_value_angle_axis"></div>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org