From c92f72a0be7542ab503dd1b7cd5e4e5dceec983e Mon Sep 17 00:00:00 2001 From: Johannes Ewald Date: Mon, 7 Apr 2025 17:02:50 +0200 Subject: [PATCH] fix(core): Restore original property descriptor on unregister Fixes a potential "Maximum callstack size exceeded" error. The current implementation doesn't cleanup the defineProperty call on the element. For every register() call, a new object descriptor is created which calls the previous one and so on. After a lot of calls of register() and unregister(), the JS engine will finally throw a callstack size error. --- packages/core/src/Input.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/core/src/Input.ts b/packages/core/src/Input.ts index 726d98f..ba543e4 100644 --- a/packages/core/src/Input.ts +++ b/packages/core/src/Input.ts @@ -25,6 +25,7 @@ export default class Input { constructor({ init, tracking }: InputOptions) { const handlersMap = new WeakMap(); + const descriptorMap = new WeakMap(); this.register = (element) => { if (!ALLOWED_TYPES.includes(element.type)) { @@ -72,6 +73,7 @@ export default class Input { // Поскольку значение элемента может быть изменено вне текущей логики, // нам важно перехватывать каждое изменение для обновления `tracker.value`. // `tracker.value` служит заменой `_valueTracker.getValue()` предоставляемый React. + descriptorMap.set(element, descriptor); Object.defineProperty(element, 'value', { ...descriptor, set: (value: string) => { @@ -240,6 +242,16 @@ export default class Input { }; this.unregister = (element) => { + const descriptor = descriptorMap.get(element); + + if (descriptor !== undefined) { + const { value } = element; + + Object.defineProperty(element, 'value', descriptor); + descriptorMap.delete(element); + element.value = value; + } + const handlers = handlersMap.get(element); if (handlers !== undefined) {