Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/util/merge.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,15 @@ function mergeExtend(iChartOption, baseOption) {
let extend = iChartOption.extend;
if (!extend) return;
for (const key in extend) {
if (Object.hasOwnProperty.call(extend, key)) {
baseOption[key] = extend[key];
// 部分替换
if (extend.partial){
if (Object.hasOwnProperty.call(extend, key)) {
merge(baseOption[key], extend[key])
}
} else {
if (Object.hasOwnProperty.call(extend, key)) {
baseOption[key] = extend[key];
}
Comment on lines 65 to +74
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix partial-merge path: it can drop updates and mutate with control metadata.

On Line 69, merge(baseOption[key], extend[key]) ignores the returned value, so new keys / some partial updates are lost. It can also fail when baseOption[key] is primitive and extend[key] is object. Also, the loop currently processes partial itself, which can leak control metadata into baseOption.

Proposed fix
 function mergeExtend(iChartOption, baseOption) {
     if (!iChartOption) return;
     let extend = iChartOption.extend;
     if (!extend) return;
     for (const key in extend) {
-        // 部分替换
-        if (extend.partial){
-            if (Object.hasOwnProperty.call(extend, key)) {
-                merge(baseOption[key], extend[key])
-            }
-        } else {
-            if (Object.hasOwnProperty.call(extend, key)) {
-                baseOption[key] = extend[key];
-            }
-        }
+        if (!Object.prototype.hasOwnProperty.call(extend, key) || key === 'partial') continue;
+        // 部分替换
+        if (extend.partial) {
+            if (isObject(extend[key]) && !isArray(extend[key])) {
+                const current = isObject(baseOption[key]) && !isArray(baseOption[key]) ? baseOption[key] : undefined;
+                baseOption[key] = merge(current, extend[key]);
+            } else {
+                baseOption[key] = extend[key];
+            }
+        } else {
+            baseOption[key] = extend[key];
+        }
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/util/merge.js` around lines 65 - 74, The partial-merge branch of merge is
dropping updates and leaking control metadata; update the loop so it skips the
control key 'partial', and when merging do not ignore the returned value:
compute const merged = merge(baseOption[key] ?? {}, extend[key]) (or if
baseOption[key] is a primitive, coerce to an object/container first), then
assign baseOption[key] = merged; keep the Object.hasOwnProperty.call(extend,
key) guard and ensure you don't mutate extend or copy the 'partial' flag into
baseOption.

}
}
}
Expand Down