Skip to content

Commit

Permalink
naive implementation of derived attribute tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
thescientist13 committed Jan 2, 2024
1 parent 4d06c3c commit ab02ab7
Showing 1 changed file with 36 additions and 6 deletions.
42 changes: 36 additions & 6 deletions src/jsx-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,16 @@ function findThisReferences(context, statement) {
// const { description } = this.todo;
references.push(init.property.name);
} else if (init.type === 'ThisExpression' && id && id.properties) {
// const { description } = this.todo;
// const { id, description } = this;
id.properties.forEach((property) => {
references.push(property.key.name);
});
} else {
// TODO we are just blindly tracking anything here.
// everything should ideally be mapped to actual this references, to create a strong chain of direct reactivity
// instead of tracking any declaration as a derived tracking attr
// for convenience here, we push the entire declaration here, instead of the name like for direct this references (see above)
references.push(declaration);
}
});
}
Expand Down Expand Up @@ -275,8 +281,6 @@ 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'
Expand Down Expand Up @@ -324,12 +328,34 @@ export function parseJsx(moduleURL) {
}

let newModuleContents = escodegen.generate(tree);
const trackingAttrs = observedAttributes.filter(attr => typeof attr === 'string');
// TODO ideally derivedAttrs would explicitely reference trackingAttrs
// and if there are no derivedAttrs, do not include the derivedGetters / derivedSetters code in the compiled output
const derivedAttrs = observedAttributes.filter(attr => typeof attr !== 'string');
const derivedGetters = derivedAttrs.map(attr => {
return `
get_${attr.id.name}(${trackingAttrs.join(',')}) {
console.log('@@@@@@@@@@@@@@@@@@@@ updating derivative value for => ${attr.id.name}');
console.log('@@@@@@@@@@@@@@@@@@@@ new derivative value is =>', ${moduleContents.slice(attr.init.start, attr.init.end)});
return ${moduleContents.slice(attr.init.start, attr.init.end)}
}
`;
}).join('\n');
const derivedSetters = derivedAttrs.map(attr => {
const name = attr.id.name;

return `
const old_${name} = this.get_${name}(oldValue);
const new_${name} = this.get_${name}(newValue);
this.update('${name}', old_${name}, new_${name});
`;
}).join('\n');

// TODO better way to determine value type?
/* eslint-disable indent */
newModuleContents = `${newModuleContents.slice(0, insertPoint)}
static get observedAttributes() {
return [${[...observedAttributes].map(attr => `'${attr}'`).join(',')}]
return [${[...trackingAttrs].map(attr => `'${attr}'`).join()}]
}
attributeChangedCallback(name, oldValue, newValue) {
Expand All @@ -347,7 +373,7 @@ export function parseJsx(moduleURL) {
}
if (newValue !== oldValue) {
switch(name) {
${observedAttributes.map((attr) => {
${trackingAttrs.map((attr) => {
return `
case '${attr}':
this.${attr} = getValue(newValue);
Expand Down Expand Up @@ -380,17 +406,21 @@ export function parseJsx(moduleURL) {
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;
}
})
if ([${[...trackingAttrs].map(attr => `'${attr}'`).join()}].includes(name)) {
${derivedSetters}
}
console.debug('****************************');
}
${derivedGetters}
${newModuleContents.slice(insertPoint)}
`;
/* eslint-enable indent */
Expand Down

0 comments on commit ab02ab7

Please sign in to comment.