make nested binds work properly

This commit is contained in:
CoolElectronics 2024-03-11 17:19:24 -04:00
parent 066d6e70eb
commit c09027d0c3
No known key found for this signature in database
GPG key ID: F63593D168636C50

View file

@ -175,6 +175,19 @@ function JSXAddFixedWrapper(ptr, cb, $if) {
}) })
} }
// returns a function that sets a reference
// the currying is a small optimization
const curryset = ptr => val =>{
let next = ptr[PROXY];
let steps = ptr[STEPS];
let i =0;
for (;i<steps.length-1;i++) {
next = next[steps[i]];
if (!isobj(next)) return;
}
next[steps[i]] = val;
}
// Actual JSX factory. Responsible for creating the HTML elements and all of the *reactive* syntactic sugar // Actual JSX factory. Responsible for creating the HTML elements and all of the *reactive* syntactic sugar
function h(type, props, ...children) { function h(type, props, ...children) {
if (type == Fragment) return children; if (type == Fragment) return children;
@ -187,10 +200,10 @@ function h(type, props, ...children) {
if (name.startsWith("bind:")) { if (name.startsWith("bind:")) {
assert(isDLPtr(ptr), "bind: requires a reference pointer from use"); assert(isDLPtr(ptr), "bind: requires a reference pointer from use");
const set = curryset(ptr);
const propname = name.substring(5); const propname = name.substring(5);
if (propname == "this") { if (propname == "this") {
// todo! support nesting set(newthis);
ptr[PROXY][ptr[STEPS][0]] = newthis;
} else { } else {
// component two way data binding!! (exact same behavior as svelte:bind) // component two way data binding!! (exact same behavior as svelte:bind)
let isRecursive = false; let isRecursive = false;
@ -209,7 +222,7 @@ function h(type, props, ...children) {
return; return;
} }
isRecursive = true; isRecursive = true;
ptr[PROXY][ptr[STEPS][0]] = value; set(value);
}); });
} }
delete props[name]; delete props[name];
@ -263,19 +276,17 @@ function h(type, props, ...children) {
if (name.startsWith("bind:")) { if (name.startsWith("bind:")) {
assert(isDLPtr(ptr), "bind: requires a reference pointer from use"); assert(isDLPtr(ptr), "bind: requires a reference pointer from use");
const propname = name.substring(5); const propname = name.substring(5);
// create the function to set the value of the pointer
let set = curryset(ptr);
if (propname == "this") { if (propname == "this") {
// todo! support nesting set(elm);
ptr[PROXY][ptr[STEPS][0]] = elm;
} else if (propname == "value") { } else if (propname == "value") {
handle(ptr, value => elm.value = value); handle(ptr, value => elm.value = value);
elm.addEventListener("change", () => { elm.addEventListener("change", () => set(elm.value))
ptr[PROXY][ptr[STEPS][0]] = elm.value;
})
} else if (propname == "checked") { } else if (propname == "checked") {
handle(ptr, value => elm.checked = value); handle(ptr, value => elm.checked = value);
elm.addEventListener("click", () => { elm.addEventListener("click", () => set(elm.checked))
ptr[PROXY][ptr[STEPS][0]] = elm.checked;
})
} }
delete props[name]; delete props[name];
} }
@ -352,13 +363,8 @@ function JSXAddChild(child, cb) {
// Where properties are assigned to elements, and where the *non-reactive* syntax sugar goes // Where properties are assigned to elements, and where the *non-reactive* syntax sugar goes
function JSXAddAttributes(elm, name, prop) { function JSXAddAttributes(elm, name, prop) {
if (typeof prop === "function" && name === "mount") { if (name.startsWith("on:")) {
window.$el = elm; assert(typeof prop === "function", "on: requires a function");
prop(elm);
return;
}
if (typeof prop === "function" && name.startsWith("on:")) {
const names = name.substring(3); const names = name.substring(3);
for (const name of names.split("$")) { for (const name of names.split("$")) {
elm.addEventListener(name, (...args) => { elm.addEventListener(name, (...args) => {