Allow variadic arguments to m.fragment (#2328)

* Implement support for variadic arguments to `m.fragment`

While I was at it, I refactored the common logic out of `hyperscript`.

* Add a missed change from #2326

* Update docs + changelog [skip ci]

* Explain rationale for `hyperscriptVnode`'s calling convention

This way, it doesn't get erroneously "cleaned up" into something worse,
and so it's clearer how it'd be potentially optimized once ES5 support
is dropped.
This commit is contained in:
Isiah Meadows 2018-12-05 23:57:42 -05:00 committed by GitHub
parent 843f420291
commit 966e78bcab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 256 additions and 43 deletions

View file

@ -1,6 +1,7 @@
"use strict"
var Vnode = require("../render/vnode")
var hyperscriptVnode = require("./hyperscriptVnode")
var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g
var selectorCache = {}
@ -29,18 +30,21 @@ function compileSelector(selector) {
return selectorCache[selector] = {tag: tag, attrs: attrs}
}
function execSelector(state, attrs, children) {
var hasAttrs = false, childList, text
var classAttr = hasOwn.call(attrs, "class") ? "class" : "className"
var className = attrs[classAttr]
function execSelector(state, vnode) {
var attrs = vnode.attrs
var children = Vnode.normalizeChildren(vnode.children)
var hasClass = hasOwn.call(attrs, "class")
var className = hasClass ? attrs.class : attrs.className
vnode.tag = state.tag
vnode.attrs = null
vnode.children = undefined
if (!isEmpty(state.attrs) && !isEmpty(attrs)) {
var newAttrs = {}
for(var key in attrs) {
if (hasOwn.call(attrs, key)) {
newAttrs[key] = attrs[key]
}
for (var key in attrs) {
if (hasOwn.call(attrs, key)) newAttrs[key] = attrs[key]
}
attrs = newAttrs
@ -60,22 +64,22 @@ function execSelector(state, attrs, children) {
? state.attrs.className
: null
if (classAttr === "class") attrs.class = null
if (hasClass) attrs.class = null
for (var key in attrs) {
if (hasOwn.call(attrs, key) && key !== "key") {
hasAttrs = true
vnode.attrs = attrs
break
}
}
if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") {
text = children[0].children
vnode.text = children[0].children
} else {
childList = children
vnode.children = children
}
return Vnode(state.tag, attrs.key, hasAttrs ? attrs : null, childList, text)
return vnode
}
function hyperscript(selector) {
@ -83,27 +87,13 @@ function hyperscript(selector) {
throw Error("The selector must be either a string or a component.");
}
var attrs = arguments[1], start = 2, children
if (attrs == null) {
attrs = {}
} else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) {
attrs = {}
start = 1
}
if (arguments.length === start + 1) {
children = arguments[start]
if (!Array.isArray(children)) children = [children]
} else {
children = []
while (start < arguments.length) children.push(arguments[start++])
}
var vnode = hyperscriptVnode.apply(1, arguments)
if (typeof selector === "string") {
return execSelector(selectorCache[selector] || compileSelector(selector), attrs, Vnode.normalizeChildren(children))
return execSelector(selectorCache[selector] || compileSelector(selector), vnode)
} else {
return Vnode(selector, attrs.key, attrs, children)
vnode.tag = selector
return vnode
}
}