diff --git a/CHANGELOG.md b/CHANGELOG.md index c1285a71..f9fb2c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Make the `each` expression handle `Map`-like instances correctly * Fix `each` expression not supporting function calls * Don't render manually created custom element on initial attachment to the DOM if it has already been manually rendered +* Clear `addElementGetter` and `addElementsGetter` cache when rendering ## 2.3.18 (2024-02-25) diff --git a/lib/element/custom_element.js b/lib/element/custom_element.js index 1bb8b632..abe847f1 100644 --- a/lib/element/custom_element.js +++ b/lib/element/custom_element.js @@ -1,4 +1,4 @@ -var has_premature_undried_elements, +let has_premature_undried_elements, originalCreateElement, creating_element, observed_attributes = Symbol('observed_attributes'), @@ -155,15 +155,15 @@ Hawkejs._createUnconstructedElement = function _createUnconstructedElement(name) * * @author Jelle De Loecker * @since 1.1.1 - * @version 1.1.1 + * @version 2.3.19 * * @param {Element} instance * * @return {Object} */ -function getPrivate(instance) { +const getPrivate = instance => { - var map = weak_properties.get(instance); + let map = weak_properties.get(instance); if (!map) { map = { @@ -176,16 +176,18 @@ function getPrivate(instance) { // Attribute string values values : {}, - // New values that are beign set - new_values : {} + // New values that are being set + new_values : {}, + + // Cached element getters + cached_elements : new Map(), }; weak_properties.set(instance, map); } return map; -} - +}; /** * Is the given name allowed as a property? @@ -884,7 +886,7 @@ Element.setStatic(function setAssignedProperty(name, getter, setter) { * * @author Jelle De Loecker * @since 2.0.0 - * @version 2.1.0 + * @version 2.3.19 * * @param {String|Object} name * @param {String} query @@ -901,15 +903,17 @@ Element.setStatic(function addElementGetter(name, query) { return; } - let symbol = Symbol(name); - this.setProperty(name, function performQuery() { - if (this[symbol] == null) { - this[symbol] = this.querySelector(query); + let private_map = getPrivate(this), + result = private_map.cached_elements.get(name); + + if (result == null) { + result = this.querySelector(query); + private_map.cached_elements.set(name, result); } - return this[symbol]; + return result; }); }); @@ -918,7 +922,7 @@ Element.setStatic(function addElementGetter(name, query) { * * @author Jelle De Loecker * @since 2.0.0 - * @version 2.1.0 + * @version 2.3.19 */ Element.setStatic(function addElementsGetter(name, query) { @@ -932,17 +936,18 @@ Element.setStatic(function addElementsGetter(name, query) { return; } - let symbol = Symbol(name); - this.setProperty(name, function performQuery() { - if (this[symbol] == null) { - this[symbol] = this.querySelectorAll(query); + let private_map = getPrivate(this), + result = private_map.cached_elements.get(name); + + if (result == null) { + result = this.querySelectorAll(query); + private_map.cached_elements.set(name, result); } - return this[symbol]; + return result; }); - }); /** @@ -973,6 +978,12 @@ function renderCustomTemplate(re_render) { let template = this.inner_template, has_prepare_logic = typeof this.prepareRenderVariables == 'function'; + // Get the private map + let private_map = getPrivate(this); + + // And clear the element cache + private_map.cached_elements.clear(); + if (!template) { return this.prepareRenderVariables(); } diff --git a/test/11-custom_elements.js b/test/11-custom_elements.js index fa1eb6e6..b0ff08d6 100644 --- a/test/11-custom_elements.js +++ b/test/11-custom_elements.js @@ -660,6 +660,30 @@ describe('CustomElement', function() { }); }); + describe('.addElementGetter(name, selector)', () => { + it('should return the correct element', async () => { + + let custom_element = Hawkejs.Hawkejs.createElement('my-sync-span'); + await custom_element.rerender(); + + assert.strictEqual(custom_element.innerHTML, 'Test this sync template!'); + + let main_span = custom_element.main_span; + + assert.strictEqual(main_span.tagName, 'SPAN'); + + main_span.textContent = 'Changed!'; + + assert.strictEqual(custom_element.innerHTML, 'Changed!'); + + await custom_element.rerender(); + assert.strictEqual(custom_element.innerHTML, 'Test this sync template!'); + + main_span = custom_element.main_span; + assert.strictEqual(main_span.innerHTML, 'Test this sync template!'); + }); + }); + describe('#rendered()', () => { it('should call back when the element has been rendered', (done) => { diff --git a/test/helpers/my_sync_span.js b/test/helpers/my_sync_span.js index b5918bca..168b0764 100644 --- a/test/helpers/my_sync_span.js +++ b/test/helpers/my_sync_span.js @@ -14,4 +14,13 @@ var MySyncSpan = Blast.Bound.Function.inherits('Hawkejs.Element', 'MySyncSpan'); * @since 0.1.0 * @version 0.1.0 */ -MySyncSpan.setTemplate('Test this sync template!', true); \ No newline at end of file +MySyncSpan.setTemplate('Test this sync template!', true); + +/** + * Get the main span + * + * @author Jelle De Loecker + * @since 2.3.19 + * @version 2.3.19 + */ +MySyncSpan.addElementGetter('main_span', 'span.test'); \ No newline at end of file