diff --git a/.changeset/deep-set-nullish.md b/.changeset/deep-set-nullish.md new file mode 100644 index 000000000000..6f64e549fae6 --- /dev/null +++ b/.changeset/deep-set-nullish.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: prevent `deep_set` crash on nullish nested values diff --git a/packages/kit/src/runtime/form-utils.js b/packages/kit/src/runtime/form-utils.js index 1573d5bfe547..34ef0796c642 100644 --- a/packages/kit/src/runtime/form-utils.js +++ b/packages/kit/src/runtime/form-utils.js @@ -466,8 +466,8 @@ export function deep_set(object, keys, value) { check_prototype_pollution(key); const is_array = /^\d+$/.test(keys[i + 1]); - const exists = Object.hasOwn(current, key); - const inner = current[key]; + const inner = Object.hasOwn(current, key) ? current[key] : undefined; + const exists = inner != null; if (exists && is_array !== Array.isArray(inner)) { throw new Error(`Invalid array key ${keys[i + 1]}`); diff --git a/packages/kit/src/runtime/form-utils.spec.js b/packages/kit/src/runtime/form-utils.spec.js index b84e97ab1478..3859bf0ee682 100644 --- a/packages/kit/src/runtime/form-utils.spec.js +++ b/packages/kit/src/runtime/form-utils.spec.js @@ -425,4 +425,20 @@ describe('deep_set', () => { // @ts-ignore expect(Object.prototype.toString.property).toBeUndefined(); }); + + test('creates nested object when intermediate value is undefined', () => { + const target = { nested: undefined }; + + deep_set(target, ['nested', 'name'], 'hello'); + + expect(target).toEqual({ nested: { name: 'hello' } }); + }); + + test('creates nested object when intermediate value is null', () => { + const target = { nested: null }; + + deep_set(target, ['nested', 'name'], 'hello'); + + expect(target).toEqual({ nested: { name: 'hello' } }); + }); });