]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Fix interoperability issue regarding Event properties (#36386)
authorAleksander Machniak <machniak@kolabsys.com>
Thu, 30 Jun 2022 19:52:47 +0000 (21:52 +0200)
committerGitHub <noreply@github.com>
Thu, 30 Jun 2022 19:52:47 +0000 (22:52 +0300)
* Fix interoperability issue regarding Event properties

- make possible to re-set read-only event properties
- use hydrateObj() to set delegateTarget property

Fixes #36207

Co-authored-by: GeoSot <geo.sotis@gmail.com>
Co-authored-by: Julien Déramond <julien.deramond@orange.com>
js/src/dom/event-handler.js
js/tests/unit/dom/event-handler.spec.js

index 87f936b41d44cd09f613f0400edf8d3e35abe009..0aa628c66dbd4b52caa97beea54e4c7eec59f9d8 100644 (file)
@@ -89,7 +89,7 @@ function getElementEvents(element) {
 
 function bootstrapHandler(element, fn) {
   return function handler(event) {
-    event.delegateTarget = element
+    hydrateObj(event, { delegateTarget: element })
 
     if (handler.oneOff) {
       EventHandler.off(element, event.type, fn)
@@ -109,7 +109,7 @@ function bootstrapDelegationHandler(element, selector, fn) {
           continue
         }
 
-        event.delegateTarget = target
+        hydrateObj(event, { delegateTarget: target })
 
         if (handler.oneOff) {
           EventHandler.off(element, event.type, selector, fn)
@@ -302,11 +302,16 @@ const EventHandler = {
 
 function hydrateObj(obj, meta) {
   for (const [key, value] of Object.entries(meta || {})) {
-    Object.defineProperty(obj, key, {
-      get() {
-        return value
-      }
-    })
+    try {
+      obj[key] = value
+    } catch {
+      Object.defineProperty(obj, key, {
+        configurable: true,
+        get() {
+          return value
+        }
+      })
+    }
   }
 
   return obj
index 14037929bca99aeef04a274b1555e1240975af1f..19d0235e6cbf509f5521fdf00ed947e923fa85c3 100644 (file)
@@ -441,4 +441,41 @@ describe('EventHandler', () => {
       expect(i).toEqual(5)
     })
   })
+
+  describe('general functionality', () => {
+    it('should hydrate properties, and make them configurable', () => {
+      return new Promise(resolve => {
+        fixtureEl.innerHTML = [
+          '<div id="div1">',
+          '   <div id="div2"></div>',
+          '   <div id="div3"></div>',
+          '</div>'
+        ].join('')
+
+        const div1 = fixtureEl.querySelector('#div1')
+        const div2 = fixtureEl.querySelector('#div2')
+        const div3 = fixtureEl.querySelector('#div3')
+
+        EventHandler.on(div1, 'click', event => {
+          event.originalTarget = div3
+
+          expect(event.currentTarget).toBe(div2)
+
+          Object.defineProperty(event, 'currentTarget', {
+            configurable: true,
+            get() {
+              return div1
+            }
+          })
+
+          expect(event.currentTarget).toBe(div1)
+          resolve()
+        })
+
+        expect(() => {
+          EventHandler.trigger(div1, 'click', { delegateTarget: div2, originalTarget: null, currentTarget: div2 })
+        }).not.toThrowError(TypeError)
+      })
+    })
+  })
 })