fix: prevent docfield copy contamination across grid rows on deletion/reorder

set_docfields was passing the row's mutated docfields (with stale
reqd/read_only/hidden from dependency evaluation) as source to
make_docfield_copy_for, poisoning the copy store for whichever doc
landed at that position after deletion/reorder.

- Remove make_docfield_copy_for call from set_docfields (the copy store
  seeds itself lazily from clean originals in get_docfield_copy)
- Always call set_docfields() on refresh so rows pick up correct copies
  when doc identity changes at a position
- Thread grid.docfields through meta.js so new copy-store entries
  include grid-level customizations (set_df_property on child fields)

Closes #36921
This commit is contained in:
Sagar Vora 2026-02-19 00:48:15 +05:30
parent ec2dbdd491
commit 9fabfa3054
2 changed files with 9 additions and 23 deletions

View file

@ -53,25 +53,14 @@ export default class GridRow {
this.wrapper.appendTo(this.parent);
}
set_docfields(update = false) {
set_docfields() {
if (this.doc && this.parent_df.options) {
frappe.meta.make_docfield_copy_for(
this.docfields = frappe.meta.get_docfields(
this.parent_df.options,
this.doc.name,
this.docfields
null,
this.grid.docfields
);
const docfields = frappe.meta.get_docfields(this.parent_df.options, this.doc.name);
if (update) {
// to maintain references
this.docfields.forEach((df) => {
Object.assign(
df,
docfields.find((d) => d.fieldname === df.fieldname)
);
});
} else {
this.docfields = docfields;
}
}
}
@ -198,10 +187,7 @@ export default class GridRow {
);
}
refresh() {
// update docfields for new record
if (this.frm && this.doc && this.doc.__islocal) {
this.set_docfields(true);
}
this.set_docfields();
if (this.frm && this.doc) {
this.doc = locals[this.doc.doctype][this.doc.name];

View file

@ -91,8 +91,8 @@ $.extend(frappe.meta, {
};
},
get_docfields: function (doctype, name, filters) {
var docfield_map = frappe.meta.get_docfield_copy(doctype, name);
get_docfields: function (doctype, name, filters, docfield_list = null) {
var docfield_map = frappe.meta.get_docfield_copy(doctype, name, docfield_list);
var docfields = frappe.meta.sort_docfields(docfield_map);
@ -125,11 +125,11 @@ $.extend(frappe.meta, {
});
},
get_docfield_copy: function (doctype, name) {
get_docfield_copy: function (doctype, name, docfield_list = null) {
if (!name) return frappe.meta.docfield_map[doctype];
if (!(frappe.meta.docfield_copy[doctype] && frappe.meta.docfield_copy[doctype][name])) {
frappe.meta.make_docfield_copy_for(doctype, name);
frappe.meta.make_docfield_copy_for(doctype, name, docfield_list);
}
return frappe.meta.docfield_copy[doctype][name];