From b377bf8d26a71cd9f44bf64837cd2a818d1d4b42 Mon Sep 17 00:00:00 2001 From: Dmitry Sharabin Date: Fri, 1 May 2026 17:20:24 +0200 Subject: [PATCH] Populate detail on first_connected shortcut re-fires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The re-fire previously dispatched a PropChangeEvent with no detail, so a listener that read e.detail.value would crash on the catch-up dispatch while succeeding on the regular dispatch. Populate a minimal detail with source: "initial" (marker for synthetic catch-up) and value (the field whose absence caused the crash). Found while integration-testing nude-element against color-elements ( exercises this path). --- src/plugins/events/propchange.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/plugins/events/propchange.js b/src/plugins/events/propchange.js index 36dbf509..ee37f60a 100644 --- a/src/plugins/events/propchange.js +++ b/src/plugins/events/propchange.js @@ -6,6 +6,7 @@ import { symbols } from "xtensible"; import base, { events } from "./base.js"; import { props } from "../props/index.js"; +import PropChangeEvent from "../props/util/PropChangeEvent.js"; const { propchange } = symbols.new; @@ -45,12 +46,13 @@ const hooks = { let propName = this.constructor[propchange][eventName]; let value = this[propName]; - if (value !== undefined) { - this.constructor[props].firePropChangeEvent(this, eventName, { - name: propName, - prop: this.constructor[props].get(propName), - }); + if (value === undefined) { + continue; } + + let prop = this.constructor[props].get(propName); + let detail = { source: "initial", value }; + this.dispatchEvent(new PropChangeEvent(eventName, { name: propName, prop, detail })); } }, };