Skip to content

Commit

Permalink
Merge pull request #23 from developit/render-ut-fixes-update1
Browse files Browse the repository at this point in the history
Add support for features from Preact render tests
  • Loading branch information
marvinhagemeister committed Aug 5, 2018
2 parents e12f93b + 7eea322 commit 3ce7876
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 199 deletions.
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changelog

## Differences from Preact

### Major changes

1. `h` has been renamed to `createElement`
2. The VNode shape has changed
1. The children of a VNode are no longer normalized `h` and could be a nested array of children.
2. `attributes` has been renamed to `props`
3. `nodeName` is now `tag`
4. `children` is now only stored as a property on `props`: `props.children`
3. `render` no longer returns the newly created DOM element. Its return type is now `void`
4. Use the new `hydrate` to function to hydrate a server rendered DOM tree
5. Setting the DOM `style` attribute to a string is not supported
6. `setState` no longer modifies `this.state` synchronously
7. Falsy attributes values are no longer removed from the DOM. For some attributes (e.g. `spellcheck`,
the values `false` and `''` have different meaning so being able to render `false` is important.

### Minor changes

1. `addEventListener` and `removeEventListner` are called everytime an event handler is changed
2. `render(null, container)` no longer renders an empty text node but instead renders nothing

### For contributors

1. `scratch.innerHTML = ''` no longer is an effective technique to clear the DOM during testing. If you thin you need to
clear the DOM during a test, consider breaking your tests into multiple individual tests to cover your function.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"eslint": "^5.1.0",
"eslint-config-developit": "^1.1.1",
"flow-bin": "^0.76.0",
"karma": "^2.0.0",
"karma": "^2.0.5",
"karma-babel-preprocessor": "^7.0.0",
"karma-chai-sinon": "^0.1.5",
"karma-chrome-launcher": "^2.0.0",
Expand Down
18 changes: 17 additions & 1 deletion src/create-element.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ELEMENT_NODE } from './constants';
import { ELEMENT_NODE, TEXT_NODE } from './constants';

export function createElement(tag, props, children) {
if (props==null) props = {};
Expand Down Expand Up @@ -47,3 +47,19 @@ export function createVNode(type, tag, props, children, text, key) {
return { type, tag, props, /*children,*/ text, key, index: null, _children: null, _el: null, _component: null };
// return { type, tag, props, children, text, key, index: null, _children: null, _el: null, _component: null };
}

/**
* Coerce an untrusted value into a VNode
* Specifically, this should be used anywhere a user could provide a boolean, string, or number where
* a VNode or Component is desired instead
* @param {boolean | string | number | function | object} possibleVNode A possible VNode
* @returns {object | function}
*/
export function coerceToVNode(possibleVNode) {
if (typeof possibleVNode === 'boolean') return null;
if (typeof possibleVNode === 'string' || typeof possibleVNode === 'number') {
return createVNode(TEXT_NODE, null, null, null, possibleVNode, null);
}

return possibleVNode;
}
18 changes: 10 additions & 8 deletions src/diff/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TEXT_NODE, EMPTY_OBJ, EMPTY_ARR } from '../constants';
import { EMPTY_OBJ, EMPTY_ARR } from '../constants';
// import { assign } from '../util';
import { Component /* , enqueueRender */ } from '../component';
import { createVNode /*, reclaimVNode*/ } from '../create-element';
import { coerceToVNode /*, reclaimVNode*/ } from '../create-element';
import { diffChildren /*, create */ } from './children';
import { diffProps } from './props';
import { assign } from '../util';
Expand Down Expand Up @@ -257,7 +257,7 @@ export function diff(dom, parent, newTree, oldTree, context, isSvg, append, exce
}
c.context = context;
let prev = c._previousVTree;
let vnode = c._previousVTree = c.render(c.props, c.state, c.context);
let vnode = c._previousVTree = coerceToVNode(c.render(c.props, c.state, c.context));
// context = assign({}, context);
// context.__depth = (context.__depth || 0) + 1;
// context = assign({
Expand Down Expand Up @@ -552,7 +552,8 @@ function flattenChildren(children, flattened) {
// if (type==='object' && typeof Symbol!=='undefined' && Symbol.iterator in children) {
// children = Array.from(children);
// }
if (children==null) {}
// if (children==null) {}
if (children==null || typeof children === 'boolean') {}
// else if (isObject && 'pop' in children) {
else if (typeof children==='object' && ('pop' in children || Symbol.iterator in children && (children = Array.from(children)))) {
// else if (type==='object' && 'pop' in children) {
Expand Down Expand Up @@ -582,10 +583,11 @@ function flattenChildren(children, flattened) {
// pushChild(children, flattened, path, index, type);
// if (!isObject) {

if (typeof children!=='object' && typeof children!=='function') {
children = createVNode(TEXT_NODE, null, null, null, children, null);
// children = createVNode(TEXT_NODE, null, null, null, children, key);
}
// if (typeof children!=='object' && typeof children!=='function') {
// children = createVNode(TEXT_NODE, null, null, null, children, null);
// // children = createVNode(TEXT_NODE, null, null, null, children, key);
// }
children = coerceToVNode(children);

// else if (children.key == null) {
// children.key = key;
Expand Down
12 changes: 7 additions & 5 deletions src/diff/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,17 @@ function setProperty(node, name, value, oldValue, isSvg) {

// }
}
// Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6
// else if (name.charCodeAt(0)===111 && name.charCodeAt(1)===110) {
else if (name[0]==='o' && name[1]==='n') {
let listenerName = name[2].toLowerCase() + name.substring(3);
node.removeEventListener(listenerName, oldValue);
node.addEventListener(listenerName, value);
let useCapture = name !== (name=name.replace(/Capture$/, ''));
let listenerName = name.toLowerCase().substring(2);
node.removeEventListener(listenerName, oldValue, useCapture);
node.addEventListener(listenerName, value, useCapture);
}
// else if (isProperty===true) {
// else if (name in node) {
else if (!isSvg && (name in node)) {
else if (name!=='list' && !isSvg && (name in node)) {
node[name] = value==null ? '' : value;
// if (value==null || value===false) node.removeAttribute(name);
}
Expand All @@ -130,7 +132,7 @@ function setProperty(node, name, value, oldValue, isSvg) {
else if (value==null || value===false) {
node.removeAttribute(name);
}
else {
else if (typeof value!=='function') {
node.setAttribute(name, value);
}
// @TODO handle this implicitly in set?
Expand Down
6 changes: 3 additions & 3 deletions src/render.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { EMPTY_OBJ, EMPTY_ARR, TEXT_NODE } from './constants';
import { diff /*, getVNodeChildren*/ } from './diff/index';
import { diffChildren } from './diff/children';
import { createVNode } from './create-element';
import { createVNode, coerceToVNode } from './create-element';

export function render(vnode, parent) {
let oldTree = parent._previousVTree;
if (oldTree) diff(oldTree._el, parent, parent._previousVTree = vnode, oldTree, EMPTY_OBJ, false, true, null, 0, [] );
if (oldTree) diff(oldTree._el, parent, parent._previousVTree = coerceToVNode(vnode), oldTree, EMPTY_OBJ, false, true, null, 0, [] );
else hydrate(vnode, parent);
}

export function hydrate(vnode, parent) {
// let oldTree = toVNode(parent);
// diffChildren(parent, null, [vnode], oldTree.children);
parent._previousVTree = vnode;
parent._previousVTree = vnode = coerceToVNode(vnode);
diffChildren(parent, [vnode], EMPTY_ARR, EMPTY_OBJ, false, EMPTY_ARR.slice.call(parent.childNodes), 0, []);
}

Expand Down
Loading

0 comments on commit 3ce7876

Please sign in to comment.