Skip to content

Commit

Permalink
Change attribute handling, fix unowned removal
Browse files Browse the repository at this point in the history
  • Loading branch information
ryansolid committed Jun 19, 2020
1 parent 895e847 commit 4aca0d2
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 67 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dom-expressions-build",
"description": "A Fine-Grained Runtime for Performant DOM Rendering",
"version": "0.18.0",
"version": "0.19.0",
"author": "Ryan Carniato",
"license": "MIT",
"repository": {
Expand Down
68 changes: 32 additions & 36 deletions packages/babel-plugin-jsx-dom-expressions/src/dom/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,10 @@ export function setAttr(path, elem, name, value, isSVG, dynamic, prevId) {
if (attribute.alias) name = attribute.alias;
} else if (isSVG) name = name.replace(/([A-Z])/g, g => `-${g[0].toLowerCase()}`);

if (isAttribute)
return t.callExpression(t.memberExpression(elem, t.identifier("setAttribute")), [
t.stringLiteral(name),
value
]);
if (isAttribute) {
registerImportMethod(path, "setAttribute");
return t.callExpression(t.identifier("_$setAttribute"), [elem, t.stringLiteral(name), value]);
}
return t.assignmentExpression("=", t.memberExpression(elem, t.identifier(name)), value);
}

Expand Down Expand Up @@ -152,7 +151,7 @@ function transformAttributes(path, results) {
a.node.name.name === "style" &&
t.isJSXExpressionContainer(a.node.value) &&
t.isObjectExpression(a.node.value.expression) &&
!(a.node.value.expression.properties.some(p => t.isSpreadElement(p)))
!a.node.value.expression.properties.some(p => t.isSpreadElement(p))
);
if (styleAttribute) {
let i = 0,
Expand Down Expand Up @@ -210,8 +209,13 @@ function transformAttributes(path, results) {
key = t.isJSXNamespacedName(node.name)
? `${node.name.namespace.name}:${node.name.name.name}`
: node.name.name,
reservedNameSpace = t.isJSXNamespacedName(node.name) && reservedNameSpaces[node.name.namespace.name];
if (t.isJSXNamespacedName(node.name) && reservedNameSpace && !t.isJSXExpressionContainer(value)) {
reservedNameSpace =
t.isJSXNamespacedName(node.name) && reservedNameSpaces[node.name.namespace.name];
if (
t.isJSXNamespacedName(node.name) &&
reservedNameSpace &&
!t.isJSXExpressionContainer(value)
) {
node.value = value = t.JSXExpressionContainer(value);
}
if (
Expand All @@ -237,9 +241,7 @@ function transformAttributes(path, results) {
);
} else if (t.isFunction(value.expression)) {
results.exprs.unshift(
t.expressionStatement(
t.callExpression(value.expression, [elem])
)
t.expressionStatement(t.callExpression(value.expression, [elem]))
);
}
} else if (key === "children") {
Expand Down Expand Up @@ -374,7 +376,7 @@ function wrappedByText(list, startIndex) {
let index = startIndex,
wrapped;
while (--index >= 0) {
const node = list[index]
const node = list[index];
if (!node) continue;
if (node.text) {
wrapped = true;
Expand All @@ -385,7 +387,7 @@ function wrappedByText(list, startIndex) {
if (!wrapped) return false;
index = startIndex;
while (++index < list.length) {
const node = list[index]
const node = list[index];
if (!node) continue;
if (node.text) return true;
if (node.id) return false;
Expand All @@ -399,18 +401,21 @@ function transformChildren(path, results) {
nextPlaceholder,
i = 0;
const filteredChildren = filterChildren(path.get("children"), true),
childNodes = filteredChildren.map((child, index) =>
transformNode(child, {
skipId: !results.id || !detectExpressions(filteredChildren, index)
})
// combine adjacent textNodes
).reduce((memo, child) => {
const i = memo.length
if (child.text && i && memo[i -1].text) {
memo[i - 1].template += child.template;
} else memo.push(child);
return memo;
}, []);
childNodes = filteredChildren
.map(
(child, index) =>
transformNode(child, {
skipId: !results.id || !detectExpressions(filteredChildren, index)
})
// combine adjacent textNodes
)
.reduce((memo, child) => {
const i = memo.length;
if (child.text && i && memo[i - 1].text) {
memo[i - 1].template += child.template;
} else memo.push(child);
return memo;
}, []);

childNodes.forEach((child, index) => {
if (!child) return;
Expand All @@ -437,22 +442,13 @@ function transformChildren(path, results) {
const multi = checkLength(filteredChildren),
markers = (generate === "dom-ssr" || hydratable) && multi;
// boxed by textNodes
if (
markers ||
wrappedByText(childNodes, index)
) {
if (markers || wrappedByText(childNodes, index)) {
let exprId, contentId;
if (markers) tempPath = createPlaceholder(path, results, tempPath, i++, "#")[0].name;
if (nextPlaceholder) {
exprId = nextPlaceholder;
} else {
[exprId, contentId] = createPlaceholder(
path,
results,
tempPath,
i++,
markers ? "/" : ""
);
[exprId, contentId] = createPlaceholder(path, results, tempPath, i++, markers ? "/" : "");
}
if (!markers) nextPlaceholder = exprId;
results.exprs.push(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { template as _$template } from "r-dom";
import { createComponent as _$createComponent } from "r-dom";
import { spread as _$spread } from "r-dom";
import { setAttribute as _$setAttribute } from "r-dom";
import { effect as _$effect } from "r-dom";

const _tmpl$ = _$template(
Expand Down Expand Up @@ -35,10 +36,10 @@ const template2 = (() => {
_v$3 = state.x,
_v$4 = state.y,
_v$5 = props.stroke;
_v$ !== _p$._v$ && _el$3.setAttribute("class", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && _el$3.setAttribute("stroke-width", (_p$._v$2 = _v$2));
_v$3 !== _p$._v$3 && _el$3.setAttribute("x", (_p$._v$3 = _v$3));
_v$4 !== _p$._v$4 && _el$3.setAttribute("y", (_p$._v$4 = _v$4));
_v$ !== _p$._v$ && _$setAttribute(_el$3, "class", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && _$setAttribute(_el$3, "stroke-width", (_p$._v$2 = _v$2));
_v$3 !== _p$._v$3 && _$setAttribute(_el$3, "x", (_p$._v$3 = _v$3));
_v$4 !== _p$._v$4 && _$setAttribute(_el$3, "y", (_p$._v$4 = _v$4));
_v$5 !== _p$._v$5 && _el$3.style.setProperty("stroke-width", (_p$._v$5 = _v$5));
return _p$;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { template as _$template } from "r-dom";
import { effect as _$effect } from "r-dom";
import { currentContext as _$currentContext } from "r-dom";
import { setAttribute as _$setAttribute } from "r-dom";

const _tmpl$ = _$template(`<my-element></my-element>`, 2),
_tmpl$2 = _$template(`<my-element><header slot="head">Title</header></my-element>`, 4),
Expand All @@ -9,7 +10,7 @@ const _tmpl$ = _$template(`<my-element></my-element>`, 2),
const template = (() => {
const _el$ = _tmpl$.cloneNode(true);

_el$.setAttribute("some-attr", name);
_$setAttribute(_el$, "some-attr", name);

_el$.someProp = data;
_el$._context = _$currentContext();
Expand All @@ -25,7 +26,7 @@ const template2 = (() => {
_p$ => {
const _v$ = state.name,
_v$2 = state.data;
_v$ !== _p$._v$ && _el$2.setAttribute("some-attr", (_p$._v$ = _v$));
_v$ !== _p$._v$ && _$setAttribute(_el$2, "some-attr", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && (_el$2.someProp = _p$._v$2 = _v$2);
return _p$;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { template as _$template } from "r-dom";
import { createComponent as _$createComponent } from "r-dom";
import { runHydrationEvents as _$runHydrationEvents } from "r-dom";
import { spread as _$spread } from "r-dom";
import { setAttribute as _$setAttribute } from "r-dom";
import { effect as _$effect } from "r-dom";
import { getNextElement as _$getNextElement } from "r-dom";

Expand Down Expand Up @@ -37,10 +38,10 @@ const template2 = (() => {
_v$3 = state.x,
_v$4 = state.y,
_v$5 = props.stroke;
_v$ !== _p$._v$ && _el$3.setAttribute("class", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && _el$3.setAttribute("stroke-width", (_p$._v$2 = _v$2));
_v$3 !== _p$._v$3 && _el$3.setAttribute("x", (_p$._v$3 = _v$3));
_v$4 !== _p$._v$4 && _el$3.setAttribute("y", (_p$._v$4 = _v$4));
_v$ !== _p$._v$ && _$setAttribute(_el$3, "class", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && _$setAttribute(_el$3, "stroke-width", (_p$._v$2 = _v$2));
_v$3 !== _p$._v$3 && _$setAttribute(_el$3, "x", (_p$._v$3 = _v$3));
_v$4 !== _p$._v$4 && _$setAttribute(_el$3, "y", (_p$._v$4 = _v$4));
_v$5 !== _p$._v$5 && _el$3.style.setProperty("stroke-width", (_p$._v$5 = _v$5));
return _p$;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { template as _$template } from "r-dom";
import { effect as _$effect } from "r-dom";
import { getNextElement as _$getNextElement } from "r-dom";
import { currentContext as _$currentContext } from "r-dom";
import { setAttribute as _$setAttribute } from "r-dom";

const _tmpl$ = _$template(`<my-element></my-element>`, 2),
_tmpl$2 = _$template(`<my-element><header slot="head">Title</header></my-element>`, 4),
Expand All @@ -10,7 +11,7 @@ const _tmpl$ = _$template(`<my-element></my-element>`, 2),
const template = (() => {
const _el$ = _$getNextElement(_tmpl$);

_el$.setAttribute("some-attr", name);
_$setAttribute(_el$, "some-attr", name);

_el$.someProp = data;
_el$._context = _$currentContext();
Expand All @@ -26,7 +27,7 @@ const template2 = (() => {
_p$ => {
const _v$ = state.name,
_v$2 = state.data;
_v$ !== _p$._v$ && _el$2.setAttribute("some-attr", (_p$._v$ = _v$));
_v$ !== _p$._v$ && _$setAttribute(_el$2, "some-attr", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && (_el$2.someProp = _p$._v$2 = _v$2);
return _p$;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { template as _$template } from "r-dom";
import { createComponent as _$createComponent } from "r-dom";
import { spread as _$spread } from "r-dom";
import { setAttribute as _$setAttribute } from "r-dom";
import { effect as _$effect } from "r-dom";
import { getNextElement as _$getNextElement } from "r-dom";

Expand Down Expand Up @@ -36,10 +37,10 @@ const template2 = (() => {
_v$3 = state.x,
_v$4 = state.y,
_v$5 = props.stroke;
_v$ !== _p$._v$ && _el$3.setAttribute("class", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && _el$3.setAttribute("stroke-width", (_p$._v$2 = _v$2));
_v$3 !== _p$._v$3 && _el$3.setAttribute("x", (_p$._v$3 = _v$3));
_v$4 !== _p$._v$4 && _el$3.setAttribute("y", (_p$._v$4 = _v$4));
_v$ !== _p$._v$ && _$setAttribute(_el$3, "class", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && _$setAttribute(_el$3, "stroke-width", (_p$._v$2 = _v$2));
_v$3 !== _p$._v$3 && _$setAttribute(_el$3, "x", (_p$._v$3 = _v$3));
_v$4 !== _p$._v$4 && _$setAttribute(_el$3, "y", (_p$._v$4 = _v$4));
_v$5 !== _p$._v$5 && _el$3.style.setProperty("stroke-width", (_p$._v$5 = _v$5));
return _p$;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { template as _$template } from "r-dom";
import { effect as _$effect } from "r-dom";
import { getNextElement as _$getNextElement } from "r-dom";
import { currentContext as _$currentContext } from "r-dom";
import { setAttribute as _$setAttribute } from "r-dom";

const _tmpl$ = _$template(`<my-element></my-element>`, 2),
_tmpl$2 = _$template(`<my-element><header slot="head">Title</header></my-element>`, 4),
Expand All @@ -10,7 +11,7 @@ const _tmpl$ = _$template(`<my-element></my-element>`, 2),
const template = (() => {
const _el$ = _$getNextElement(_tmpl$, true);

_el$.setAttribute("some-attr", name);
_$setAttribute(_el$, "some-attr", name);

_el$.someProp = data;
_el$._context = _$currentContext();
Expand All @@ -26,7 +27,7 @@ const template2 = (() => {
_p$ => {
const _v$ = state.name,
_v$2 = state.data;
_v$ !== _p$._v$ && _el$2.setAttribute("some-attr", (_p$._v$ = _v$));
_v$ !== _p$._v$ && _$setAttribute(_el$2, "some-attr", (_p$._v$ = _v$));
_v$2 !== _p$._v$2 && (_el$2.someProp = _p$._v$2 = _v$2);
return _p$;
},
Expand Down
1 change: 1 addition & 0 deletions packages/dom-expressions/src/runtime.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function delegateEvents(eventNames: string[]): void;
export function clearDelegatedEvents(): void;
export function spread(node: Element, accessor: any, isSVG?: Boolean, skipChildren?: Boolean): void;
export function assign(node: Element, props: any, isSVG?: Boolean, skipChildren?: Boolean): void;
export function setAttribute(node : Element, name : string, value : any): void;
export function classList(
node: Element,
value: { [k: string]: boolean },
Expand Down
30 changes: 18 additions & 12 deletions packages/dom-expressions/src/runtime.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Attributes, SVGAttributes, NonComposedEvents } from "./constants";
import { root, effect, memo, currentContext, createComponent } from "rxcore";
import { root, effect, memo, currentContext, createComponent } from "rxcore";
import reconcileArrays from "./reconcile";

const eventRegistry = new Set(),
Expand All @@ -21,7 +21,7 @@ export function renderToString(code, options = {}) {
hydration.context = { id: "0", count: 0 };
return root(() => {
const rendered = code();
if (typeof rendered === "object" && 'then' in rendered) {
if (typeof rendered === "object" && "then" in rendered) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject("renderToString timed out"), options.timeoutMs)
);
Expand All @@ -46,7 +46,7 @@ export function renderDOMToString(code, options = {}) {
return html;
}

if (typeof rendered === "object" && 'then' in rendered) {
if (typeof rendered === "object" && "then" in rendered) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject("renderToString timed out"), options.timeoutMs)
);
Expand Down Expand Up @@ -99,6 +99,11 @@ export function clearDelegatedEvents() {
eventRegistry.clear();
}

export function setAttribute(node, name, value) {
if (value === false || value == null) node.removeAttribute(name);
else node.setAttribute(name, value);
}

export function classList(node, value, prev) {
const classKeys = Object.keys(value);
for (let i = 0, len = classKeys.length; i < len; i++) {
Expand Down Expand Up @@ -200,13 +205,13 @@ export function ssr(template, ...nodes) {
}
const t = () => {
let result = "";
for(let i = 0; i < template.length; i++) {
for (let i = 0; i < template.length; i++) {
result += template[i];
const node = rNodes[i];
if (node !== undefined) result += resolveSSRNode(node);
}
return result;
}
};
t.isTemplate = true;
return t;
}
Expand Down Expand Up @@ -265,13 +270,13 @@ export function escape(html, attr) {
if (typeof html !== "string") return html;
return html.replace(attr ? ATTR_REGEX : CONTENT_REGEX, m => {
switch (m) {
case '&':
return '&amp;';
case '<':
return '&lt;';
case "&":
return "&amp;";
case "<":
return "&lt;";
case '"':
return '&quot;';
}
return "&quot;";
}
});
}

Expand Down Expand Up @@ -471,7 +476,8 @@ function cleanChildren(parent, current, marker, replacement) {
const node = replacement || document.createTextNode("");
if (current.length) {
node !== current[0] && parent.replaceChild(node, current[0]);
for (let i = current.length - 1; i > 0; i--) parent.removeChild(current[i]);
for (let i = current.length - 1; i > 0; i--)
current[i].parentNode === parent && parent.removeChild(current[i]);
} else parent.insertBefore(node, marker);
return [node];
}
Expand Down

0 comments on commit 4aca0d2

Please sign in to comment.