From 344f0e3fc6ad68aeb999a203d4f712802853c133 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Wed, 28 Jan 2026 15:43:43 +0100 Subject: [PATCH 1/4] Provide no_string arg in createMemberStreamer In some cases `kOffsetL + kChar` type should be read as array and not as string. --- modules/io.mjs | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/modules/io.mjs b/modules/io.mjs index 4d4c7b38b..5cbaf14d0 100644 --- a/modules/io.mjs +++ b/modules/io.mjs @@ -979,7 +979,7 @@ function readMapElement(buf) { /** @summary create member entry for streamer element * @desc used for reading of data * @private */ -function createMemberStreamer(element, file) { +function createMemberStreamer(element, file, no_string) { const member = { name: element.fName, type: element.fType, fArrayLength: element.fArrayLength, @@ -1045,6 +1045,7 @@ function createMemberStreamer(element, file) { case kOffsetL + kInt: case kOffsetL + kCounter: case kOffsetL + kDouble: + case kOffsetL + kChar: case kOffsetL + kUChar: case kOffsetL + kShort: case kOffsetL + kUShort: @@ -1057,31 +1058,29 @@ function createMemberStreamer(element, file) { case kOffsetL + kFloat: if (element.fArrayDim < 2) { member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { - obj[this.name] = buf.readFastArray(this.arrlength, this.type - kOffsetL); - }; + if ((member.type !== kOffsetL + kChar) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = buf.readFastArray(this.arrlength, this.type - kOffsetL); + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = buf.readFastString(this.arrlength); + }; + } } else { - member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; member.minus1 = true; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => - buf2.readFastArray(handle.arrlength, handle.type - kOffsetL)); - }; - } - break; - case kOffsetL + kChar: - if (element.fArrayDim < 2) { - member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { - obj[this.name] = buf.readFastString(this.arrlength); - }; - } else { - member.minus1 = true; // one dimension used for char* member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => - buf2.readFastString(handle.arrlength)); - }; + if ((member.type !== kOffsetL + kChar) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => + buf2.readFastArray(handle.arrlength, handle.type - kOffsetL)); + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => + buf2.readFastString(handle.arrlength)); + }; + } } break; case kOffsetP + kBool: From de602cdec75b40ef09b849b694969f060be5c667 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Wed, 28 Jan 2026 15:44:49 +0100 Subject: [PATCH 2/4] Use no_string in array-based tree processing If branch values processed as array - they always should be read as arrays. So specify no_string for such case --- modules/tree.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tree.mjs b/modules/tree.mjs index 99f499732..9a5709799 100644 --- a/modules/tree.mjs +++ b/modules/tree.mjs @@ -2488,7 +2488,7 @@ async function treeProcess(tree, selector, args) { elem.fArrayDim = 1; elem.fMaxIndex[0] = 10; // 10 if artificial number, will be replaced during reading - item.arrmember = createMemberStreamer(elem, handle.file); + item.arrmember = createMemberStreamer(elem, handle.file, true); } } } else From f144cc2520dbe287928f814487b575933adccff5 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Wed, 28 Jan 2026 15:47:02 +0100 Subject: [PATCH 3/4] Also for kOffsetP + kChar support no_string arg --- modules/io.mjs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/io.mjs b/modules/io.mjs index 5cbaf14d0..52a8943d6 100644 --- a/modules/io.mjs +++ b/modules/io.mjs @@ -1086,6 +1086,7 @@ function createMemberStreamer(element, file, no_string) { case kOffsetP + kBool: case kOffsetP + kInt: case kOffsetP + kDouble: + case kOffsetP + kChar: case kOffsetP + kUChar: case kOffsetP + kShort: case kOffsetP + kUShort: @@ -1097,15 +1098,15 @@ function createMemberStreamer(element, file, no_string) { case kOffsetP + kLong64: case kOffsetP + kFloat: member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? buf.readFastArray(obj[this.cntname], this.type - kOffsetP) : []; - }; - break; - case kOffsetP + kChar: - member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? buf.readFastString(obj[this.cntname]) : null; - }; + if ((member.type !== kOffsetP + kChar) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? buf.readFastArray(obj[this.cntname], this.type - kOffsetP) : []; + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? buf.readFastString(obj[this.cntname]) : null; + }; + } break; case kDouble32: case kOffsetL + kDouble32: From ba7df7e8404eca1bd0e599cc0da197608ed0a7ba Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Wed, 28 Jan 2026 15:49:04 +0100 Subject: [PATCH 4/4] Build with tree fix --- build/jsroot.js | 77 +++++++++++++++++++++++++----------------------- changes.md | 1 + modules/core.mjs | 2 +- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/build/jsroot.js b/build/jsroot.js index 34c8e04cc..342f80833 100644 --- a/build/jsroot.js +++ b/build/jsroot.js @@ -14,7 +14,7 @@ const version_id = 'dev', /** @summary version date * @desc Release date in format day/month/year like '14/04/2022' */ -version_date = '28/11/2025', +version_date = '28/01/2026', /** @summary version id and date * @desc Produced by concatenation of {@link version_id} and {@link version_date} @@ -105080,11 +105080,14 @@ let TGraphPainter$1 = class TGraphPainter extends ObjectPainter { return true; let is_normal = false; - if (check_axis !== 'y') - is_normal ||= (histo.fXaxis.fXmin !== 0.0011) || (histo.fXaxis.fXmax !== 1.1); + if (check_axis !== 'y') { + is_normal ||= ((histo.fXaxis.fXmin !== 0.0011) && (histo.fXaxis.fXmin !== 0)) || + ((histo.fXaxis.fXmax !== 1.1) && (histo.fXaxis.fXmax !== 1)); + } if (check_axis !== 'x') { - is_normal ||= (histo.fYaxis.fXmin !== 0.0011) || (histo.fYaxis.fXmax !== 1.1) || + is_normal ||= ((histo.fYaxis.fXmin !== 0.0011) && (histo.fYaxis.fXmin !== 0)) || + ((histo.fYaxis.fXmax !== 1.1) && (histo.fYaxis.fXmax !== 1)) || (histo.fMinimum !== 0.0011) || (histo.fMaximum !== 1.1); } @@ -122161,7 +122164,7 @@ function readMapElement(buf) { /** @summary create member entry for streamer element * @desc used for reading of data * @private */ -function createMemberStreamer(element, file) { +function createMemberStreamer(element, file, no_string) { const member = { name: element.fName, type: element.fType, fArrayLength: element.fArrayLength, @@ -122227,6 +122230,7 @@ function createMemberStreamer(element, file) { case kOffsetL + kInt: case kOffsetL + kCounter: case kOffsetL + kDouble: + case kOffsetL + kChar: case kOffsetL + kUChar: case kOffsetL + kShort: case kOffsetL + kUShort: @@ -122239,36 +122243,35 @@ function createMemberStreamer(element, file) { case kOffsetL + kFloat: if (element.fArrayDim < 2) { member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { - obj[this.name] = buf.readFastArray(this.arrlength, this.type - kOffsetL); - }; + if ((member.type !== kOffsetL + kChar) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = buf.readFastArray(this.arrlength, this.type - kOffsetL); + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = buf.readFastString(this.arrlength); + }; + } } else { - member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; member.minus1 = true; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => - buf2.readFastArray(handle.arrlength, handle.type - kOffsetL)); - }; - } - break; - case kOffsetL + kChar: - if (element.fArrayDim < 2) { - member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { - obj[this.name] = buf.readFastString(this.arrlength); - }; - } else { - member.minus1 = true; // one dimension used for char* member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => - buf2.readFastString(handle.arrlength)); - }; + if ((member.type !== kOffsetL + kChar) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => + buf2.readFastArray(handle.arrlength, handle.type - kOffsetL)); + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => + buf2.readFastString(handle.arrlength)); + }; + } } break; case kOffsetP + kBool: case kOffsetP + kInt: case kOffsetP + kDouble: + case kOffsetP + kChar: case kOffsetP + kUChar: case kOffsetP + kShort: case kOffsetP + kUShort: @@ -122280,15 +122283,15 @@ function createMemberStreamer(element, file) { case kOffsetP + kLong64: case kOffsetP + kFloat: member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? buf.readFastArray(obj[this.cntname], this.type - kOffsetP) : []; - }; - break; - case kOffsetP + kChar: - member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? buf.readFastString(obj[this.cntname]) : null; - }; + if ((member.type !== kOffsetP + kChar) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? buf.readFastArray(obj[this.cntname], this.type - kOffsetP) : []; + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? buf.readFastString(obj[this.cntname]) : null; + }; + } break; case kDouble32: case kOffsetL + kDouble32: @@ -127822,7 +127825,7 @@ async function treeProcess(tree, selector, args) { elem.fArrayDim = 1; elem.fMaxIndex[0] = 10; // 10 if artificial number, will be replaced during reading - item.arrmember = createMemberStreamer(elem, handle.file); + item.arrmember = createMemberStreamer(elem, handle.file, true); } } } else diff --git a/changes.md b/changes.md index b97276f2b..0b89f58b9 100644 --- a/changes.md +++ b/changes.md @@ -9,6 +9,7 @@ 1. Let define alternative draw function #378 1. Remove support for deprectaed `TH1K` class 1. Fix - paint frame border mode/size from TCanvas +1. Fix - correctly process `TLeafB` arrays in tree draw #384 ## Changes in 7.10.1 diff --git a/modules/core.mjs b/modules/core.mjs index 3fe979f42..587a14662 100644 --- a/modules/core.mjs +++ b/modules/core.mjs @@ -6,7 +6,7 @@ const version_id = 'dev', /** @summary version date * @desc Release date in format day/month/year like '14/04/2022' */ -version_date = '28/11/2025', +version_date = '28/01/2026', /** @summary version id and date * @desc Produced by concatenation of {@link version_id} and {@link version_date}