From 06194df2cbb7871392b1fa865d41255be2a0097d Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Sun, 11 Oct 2026 04:04:41 +0800 Subject: [PATCH] fix: replace null parents when resolving nested sections --- lib/ini.js | 3 ++- test/null-sections.js | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/null-sections.js diff --git a/lib/ini.js b/lib/ini.js index beb390d..8dd4e7d 100644 --- a/lib/ini.js +++ b/lib/ini.js @@ -190,7 +190,8 @@ const decode = (str, opt = {}) => { if (part === '__proto__') { continue } - if (!hasOwnProperty.call(p, part) || typeof p[part] !== 'object') { + // 2026-10-11: Null is a scalar value, so it cannot contain a nested section. + if (!hasOwnProperty.call(p, part) || p[part] === null || typeof p[part] !== 'object') { p[part] = Object.create(null) } p = p[part] diff --git a/test/null-sections.js b/test/null-sections.js new file mode 100644 index 0000000..4c506c6 --- /dev/null +++ b/test/null-sections.js @@ -0,0 +1,22 @@ +const ini = require('../') +const t = require('tap') + +// 2026-10-11: Section paths replace null ancestors just like other scalar values. +t.test('nested sections replace scalar parents', t => { + for (const value of ['null', 'false', 'text']) { + t.test(`replace a ${value} parent`, t => { + t.same(ini.parse(`a=${value}\n[a.b]\nx=1`), { + a: { b: { x: '1' } }, + }) + t.end() + }) + } + t.same(ini.parse('[a]\nb=null\n[a.b.c]\nx=1'), { + a: { b: { c: { x: '1' } } }, + }, 'replace a null parent inside a section') + t.same(ini.parse('a.b=null\n[a.b.c]\nx=1'), { + a: { b: { c: { x: '1' } } }, + }, 'replace a null parent introduced by a dotted key') + t.same(ini.parse('a=null'), { a: null }, 'retain null without a nested section') + t.end() +})