wasm-metering
Version:
injects metering into webassembly binaries
132 lines (114 loc) • 4.2 kB
JavaScript
var trailingNewlineRegex = /\n[\s]+$/
var leadingNewlineRegex = /^\n[\s]+/
var trailingSpaceRegex = /[\s]+$/
var leadingSpaceRegex = /^[\s]+/
var multiSpaceRegex = /[\n\s]+/g
var TEXT_TAGS = [
'a', 'abbr', 'b', 'bdi', 'bdo', 'br', 'cite', 'data', 'dfn', 'em', 'i',
'kbd', 'mark', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'amp', 'small', 'span',
'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr'
]
var VERBATIM_TAGS = [
'code', 'pre', 'textarea'
]
module.exports = function appendChild (el, childs) {
if (!Array.isArray(childs)) return
var nodeName = el.nodeName.toLowerCase()
var hadText = false
var value, leader
for (var i = 0, len = childs.length; i < len; i++) {
var node = childs[i]
if (Array.isArray(node)) {
appendChild(el, node)
continue
}
if (typeof node === 'number' ||
typeof node === 'boolean' ||
typeof node === 'function' ||
node instanceof Date ||
node instanceof RegExp) {
node = node.toString()
}
var lastChild = el.childNodes[el.childNodes.length - 1]
// Iterate over text nodes
if (typeof node === 'string') {
hadText = true
// If we already had text, append to the existing text
if (lastChild && lastChild.nodeName === '#text') {
lastChild.nodeValue += node
// We didn't have a text node yet, create one
} else {
node = document.createTextNode(node)
el.appendChild(node)
lastChild = node
}
// If this is the last of the child nodes, make sure we close it out
// right
if (i === len - 1) {
hadText = false
// Trim the child text nodes if the current node isn't a
// node where whitespace matters.
if (TEXT_TAGS.indexOf(nodeName) === -1 &&
VERBATIM_TAGS.indexOf(nodeName) === -1) {
value = lastChild.nodeValue
.replace(leadingNewlineRegex, '')
.replace(trailingSpaceRegex, '')
.replace(trailingNewlineRegex, '')
.replace(multiSpaceRegex, ' ')
if (value === '') {
el.removeChild(lastChild)
} else {
lastChild.nodeValue = value
}
} else if (VERBATIM_TAGS.indexOf(nodeName) === -1) {
// The very first node in the list should not have leading
// whitespace. Sibling text nodes should have whitespace if there
// was any.
leader = i === 0 ? '' : ' '
value = lastChild.nodeValue
.replace(leadingNewlineRegex, leader)
.replace(leadingSpaceRegex, ' ')
.replace(trailingSpaceRegex, '')
.replace(trailingNewlineRegex, '')
.replace(multiSpaceRegex, ' ')
lastChild.nodeValue = value
}
}
// Iterate over DOM nodes
} else if (node && node.nodeType) {
// If the last node was a text node, make sure it is properly closed out
if (hadText) {
hadText = false
// Trim the child text nodes if the current node isn't a
// text node or a code node
if (TEXT_TAGS.indexOf(nodeName) === -1 &&
VERBATIM_TAGS.indexOf(nodeName) === -1) {
value = lastChild.nodeValue
.replace(leadingNewlineRegex, '')
.replace(trailingNewlineRegex, '')
.replace(multiSpaceRegex, ' ')
// Remove empty text nodes, append otherwise
if (value === '') {
el.removeChild(lastChild)
} else {
lastChild.nodeValue = value
}
// Trim the child nodes if the current node is not a node
// where all whitespace must be preserved
} else if (VERBATIM_TAGS.indexOf(nodeName) === -1) {
value = lastChild.nodeValue
.replace(leadingSpaceRegex, ' ')
.replace(leadingNewlineRegex, '')
.replace(trailingNewlineRegex, '')
.replace(multiSpaceRegex, ' ')
lastChild.nodeValue = value
}
}
// Store the last nodename
var _nodeName = node.nodeName
if (_nodeName) nodeName = _nodeName.toLowerCase()
// Append the node to the DOM
el.appendChild(node)
}
}
}