From 4d06c3c4fa2031c26dcaba34c9c4f2e8babf9abd Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Wed, 4 Jan 2023 16:53:51 -0500 Subject: [PATCH] implementing fine grained observability --- src/jsx-loader.js | 51 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/jsx-loader.js b/src/jsx-loader.js index bef481b..62e324f 100644 --- a/src/jsx-loader.js +++ b/src/jsx-loader.js @@ -116,7 +116,8 @@ function parseJsxElement(element, moduleContents = '') { if (left.object.type === 'ThisExpression') { if (left.property.type === 'Identifier') { // very naive (fine grained?) reactivity - string += ` ${name}="__this__.${left.property.name}${expression.operator}${right.raw}; __this__.render();"`; + // string += ` ${name}="__this__.${left.property.name}${expression.operator}${right.raw}; __this__.update(\\'${left.property.name}\\', null, __this__.${left.property.name});"`; + string += ` ${name}="__this__.${left.property.name}${expression.operator}${right.raw}; __this__.setAttribute(\\'${left.property.name}\\', __this__.${left.property.name});"`; } } } @@ -144,6 +145,9 @@ function parseJsxElement(element, moduleContents = '') { } } } + + // TODO make sure this only applies to `this` references! + string += ` data-wcc-${expression.name}="${name}" data-wcc-ins="attr"`; } } else { // xxx > @@ -170,6 +174,11 @@ function parseJsxElement(element, moduleContents = '') { if (type === 'Identifier') { // You have {count} TODOs left to complete + const { name } = element.expression; + + string = `${string.slice(0, string.lastIndexOf('>'))} data-wcc-${name}="\${this.${name}}" data-wcc-ins="text">`; + // TODO be able to remove this extra data attribute + // string = `${string.slice(0, string.lastIndexOf('>'))} data-wcc-${name} data-wcc-ins="text">`; string += `\$\{${element.expression.name}\}`; } else if (type === 'MemberExpression') { const { object } = element.expression.object; @@ -266,6 +275,8 @@ export function parseJsx(moduleURL) { applyDomDepthSubstitutions(elementTree, undefined, hasShadowRoot); const finalHtml = serialize(elementTree); + console.debug({ finalHtml }); + console.debug(`${finalHtml.replace(/\n/g, '')};`); const transformed = acorn.parse(`${elementRoot}.innerHTML = \`${finalHtml}\`;`, { ecmaVersion: 'latest', sourceType: 'module' @@ -322,6 +333,9 @@ export function parseJsx(moduleURL) { } attributeChangedCallback(name, oldValue, newValue) { + console.debug('???attributeChangedCallback', { name }); + console.debug('???attributeChangedCallback', { oldValue }); + console.debug('???attributeChangedCallback', { newValue }); function getValue(value) { return value.charAt(0) === '{' || value.charAt(0) === '[' ? JSON.parse(value) @@ -341,11 +355,42 @@ export function parseJsx(moduleURL) { `; }).join('\n')} } - - this.render(); + this.update(name, oldValue, newValue); } } + update(name, oldValue, newValue) { + console.debug('Update tracking against....', this.constructor.observedAttributes); + console.debug('Updating', name); + console.debug('Swap old', oldValue); + console.debug('For new', newValue); + console.debug('this[name]', this[name]); + const attr = \`data-wcc-\${name}\`; + const selector = \`[\${attr}]\`; + console.debug({ attr }); + console.debug({ selector }); + + this.querySelectorAll(selector).forEach((el) => { + const needle = oldValue || el.getAttribute(attr); + console.debug({ el }) + console.debug({ needle }); + console.debug({ newValue }); + switch(el.getAttribute('data-wcc-ins')) { + case 'text': + el.textContent = el.textContent.replace(needle, newValue); + break; + case 'attr': + console.debug(el.hasAttribute(attr)) + if (el.hasAttribute(el.getAttribute(attr))) { + el.setAttribute(el.getAttribute(attr), newValue); + } + break; + } + }) + + console.debug('****************************'); + } + ${newModuleContents.slice(insertPoint)} `; /* eslint-enable indent */