wasm-metering
Version:
injects metering into webassembly binaries
1,054 lines (944 loc) • 31.1 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = function () {
// Allow `bel` to be swapped in benchmarking
const html = require('bel')
const greeting = 'Hello'
const name = 'special characters, <, >, &'
const drinks = [
{ name: 'Cafe Latte', price: 3.0, sold: false },
{ name: 'Cappucino', price: 2.9, sold: true },
{ name: 'Club Mate', price: 2.2, sold: true },
{ name: 'Berliner Weiße', price: 3.5, sold: false }
]
const listeners = []
function onChange (listener) {
listeners.push(listener)
}
function notifyChange () {
listeners.forEach((listener) => listener())
}
function deleteDrink (drink) {
const index = drinks.indexOf(drink)
if (index >= 0) {
drinks.splice(index, 1)
}
notifyChange()
}
function drinkView (drink, deleteDrink) {
return html`
<li>
${drink.name} is € ${drink.price}
<button ${{type: 'submit', 'data-ga-btn': 'Button'}} onclick=${() => deleteDrink(drink)} disabled="${!drink.sold}">Give me!</button>
</li>
`
}
function mainView (greeting, name, drinks, deleteDrink) {
return html`
<div>
<p>${greeting}, ${name}!</p>
${drinks.length > 0 ? html`
<ul>
${drinks.map(drink => drinkView(drink, deleteDrink))}
</ul>
` : html`
<p>All drinks are gone!</p>
`}
</div>
`
}
function render () {
return mainView(greeting, name, drinks, deleteDrink)
}
return {
render: render,
onChange: onChange
}
}
},{"bel":3}],2:[function(require,module,exports){
const nanomorph = require('nanomorph')
const createApp = require('./app')
const app = createApp()
const root = document.getElementById('root')
const tree = root.firstElementChild
nanomorph(tree, app.render())
app.onChange(() => {
nanomorph(tree, app.render())
})
},{"./app":1,"nanomorph":10}],3:[function(require,module,exports){
var document = require('global/document')
var hyperx = require('hyperx')
var onload = require('on-load')
var SVGNS = 'http://www.w3.org/2000/svg'
var XLINKNS = 'http://www.w3.org/1999/xlink'
var BOOL_PROPS = {
autofocus: 1,
checked: 1,
defaultchecked: 1,
disabled: 1,
formnovalidate: 1,
indeterminate: 1,
readonly: 1,
required: 1,
selected: 1,
willvalidate: 1
}
var COMMENT_TAG = '!--'
var SVG_TAGS = [
'svg',
'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor',
'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile',
'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix',
'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting',
'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB',
'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode',
'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting',
'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'font', 'font-face',
'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri',
'foreignObject', 'g', 'glyph', 'glyphRef', 'hkern', 'image', 'line',
'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph', 'mpath',
'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect',
'set', 'stop', 'switch', 'symbol', 'text', 'textPath', 'title', 'tref',
'tspan', 'use', 'view', 'vkern'
]
function belCreateElement (tag, props, children) {
var el
// If an svg tag, it needs a namespace
if (SVG_TAGS.indexOf(tag) !== -1) {
props.namespace = SVGNS
}
// If we are using a namespace
var ns = false
if (props.namespace) {
ns = props.namespace
delete props.namespace
}
// Create the element
if (ns) {
el = document.createElementNS(ns, tag)
} else if (tag === COMMENT_TAG) {
return document.createComment(props.comment)
} else {
el = document.createElement(tag)
}
// If adding onload events
if (props.onload || props.onunload) {
var load = props.onload || function () {}
var unload = props.onunload || function () {}
onload(el, function belOnload () {
load(el)
}, function belOnunload () {
unload(el)
},
// We have to use non-standard `caller` to find who invokes `belCreateElement`
belCreateElement.caller.caller.caller)
delete props.onload
delete props.onunload
}
// Create the properties
for (var p in props) {
if (props.hasOwnProperty(p)) {
var key = p.toLowerCase()
var val = props[p]
// Normalize className
if (key === 'classname') {
key = 'class'
p = 'class'
}
// The for attribute gets transformed to htmlFor, but we just set as for
if (p === 'htmlFor') {
p = 'for'
}
// If a property is boolean, set itself to the key
if (BOOL_PROPS[key]) {
if (val === 'true') val = key
else if (val === 'false') continue
}
// If a property prefers being set directly vs setAttribute
if (key.slice(0, 2) === 'on') {
el[p] = val
} else {
if (ns) {
if (p === 'xlink:href') {
el.setAttributeNS(XLINKNS, p, val)
} else if (/^xmlns($|:)/i.test(p)) {
// skip xmlns definitions
} else {
el.setAttributeNS(null, p, val)
}
} else {
el.setAttribute(p, val)
}
}
}
}
function appendChild (childs) {
if (!Array.isArray(childs)) return
for (var i = 0; i < childs.length; i++) {
var node = childs[i]
if (Array.isArray(node)) {
appendChild(node)
continue
}
if (typeof node === 'number' ||
typeof node === 'boolean' ||
typeof node === 'function' ||
node instanceof Date ||
node instanceof RegExp) {
node = node.toString()
}
if (typeof node === 'string') {
if (el.lastChild && el.lastChild.nodeName === '#text') {
el.lastChild.nodeValue += node
continue
}
node = document.createTextNode(node)
}
if (node && node.nodeType) {
el.appendChild(node)
}
}
}
appendChild(children)
return el
}
module.exports = hyperx(belCreateElement, {comments: true})
module.exports.default = module.exports
module.exports.createElement = belCreateElement
},{"global/document":5,"hyperx":8,"on-load":13}],4:[function(require,module,exports){
},{}],5:[function(require,module,exports){
(function (global){
var topLevel = typeof global !== 'undefined' ? global :
typeof window !== 'undefined' ? window : {}
var minDoc = require('min-document');
var doccy;
if (typeof document !== 'undefined') {
doccy = document;
} else {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
if (!doccy) {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
}
}
module.exports = doccy;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"min-document":4}],6:[function(require,module,exports){
(function (global){
var win;
if (typeof window !== "undefined") {
win = window;
} else if (typeof global !== "undefined") {
win = global;
} else if (typeof self !== "undefined"){
win = self;
} else {
win = {};
}
module.exports = win;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],7:[function(require,module,exports){
module.exports = attributeToProperty
var transform = {
'class': 'className',
'for': 'htmlFor',
'http-equiv': 'httpEquiv'
}
function attributeToProperty (h) {
return function (tagName, attrs, children) {
for (var attr in attrs) {
if (attr in transform) {
attrs[transform[attr]] = attrs[attr]
delete attrs[attr]
}
}
return h(tagName, attrs, children)
}
}
},{}],8:[function(require,module,exports){
var attrToProp = require('hyperscript-attribute-to-property')
var VAR = 0, TEXT = 1, OPEN = 2, CLOSE = 3, ATTR = 4
var ATTR_KEY = 5, ATTR_KEY_W = 6
var ATTR_VALUE_W = 7, ATTR_VALUE = 8
var ATTR_VALUE_SQ = 9, ATTR_VALUE_DQ = 10
var ATTR_EQ = 11, ATTR_BREAK = 12
var COMMENT = 13
module.exports = function (h, opts) {
if (!opts) opts = {}
var concat = opts.concat || function (a, b) {
return String(a) + String(b)
}
if (opts.attrToProp !== false) {
h = attrToProp(h)
}
return function (strings) {
var state = TEXT, reg = ''
var arglen = arguments.length
var parts = []
for (var i = 0; i < strings.length; i++) {
if (i < arglen - 1) {
var arg = arguments[i+1]
var p = parse(strings[i])
var xstate = state
if (xstate === ATTR_VALUE_DQ) xstate = ATTR_VALUE
if (xstate === ATTR_VALUE_SQ) xstate = ATTR_VALUE
if (xstate === ATTR_VALUE_W) xstate = ATTR_VALUE
if (xstate === ATTR) xstate = ATTR_KEY
p.push([ VAR, xstate, arg ])
parts.push.apply(parts, p)
} else parts.push.apply(parts, parse(strings[i]))
}
var tree = [null,{},[]]
var stack = [[tree,-1]]
for (var i = 0; i < parts.length; i++) {
var cur = stack[stack.length-1][0]
var p = parts[i], s = p[0]
if (s === OPEN && /^\//.test(p[1])) {
var ix = stack[stack.length-1][1]
if (stack.length > 1) {
stack.pop()
stack[stack.length-1][0][2][ix] = h(
cur[0], cur[1], cur[2].length ? cur[2] : undefined
)
}
} else if (s === OPEN) {
var c = [p[1],{},[]]
cur[2].push(c)
stack.push([c,cur[2].length-1])
} else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) {
var key = ''
var copyKey
for (; i < parts.length; i++) {
if (parts[i][0] === ATTR_KEY) {
key = concat(key, parts[i][1])
} else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) {
if (typeof parts[i][2] === 'object' && !key) {
for (copyKey in parts[i][2]) {
if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) {
cur[1][copyKey] = parts[i][2][copyKey]
}
}
} else {
key = concat(key, parts[i][2])
}
} else break
}
if (parts[i][0] === ATTR_EQ) i++
var j = i
for (; i < parts.length; i++) {
if (parts[i][0] === ATTR_VALUE || parts[i][0] === ATTR_KEY) {
if (!cur[1][key]) cur[1][key] = strfn(parts[i][1])
else cur[1][key] = concat(cur[1][key], parts[i][1])
} else if (parts[i][0] === VAR
&& (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) {
if (!cur[1][key]) cur[1][key] = strfn(parts[i][2])
else cur[1][key] = concat(cur[1][key], parts[i][2])
} else {
if (key.length && !cur[1][key] && i === j
&& (parts[i][0] === CLOSE || parts[i][0] === ATTR_BREAK)) {
// https://html.spec.whatwg.org/multipage/infrastructure.html#boolean-attributes
// empty string is falsy, not well behaved value in browser
cur[1][key] = key.toLowerCase()
}
break
}
}
} else if (s === ATTR_KEY) {
cur[1][p[1]] = true
} else if (s === VAR && p[1] === ATTR_KEY) {
cur[1][p[2]] = true
} else if (s === CLOSE) {
if (selfClosing(cur[0]) && stack.length) {
var ix = stack[stack.length-1][1]
stack.pop()
stack[stack.length-1][0][2][ix] = h(
cur[0], cur[1], cur[2].length ? cur[2] : undefined
)
}
} else if (s === VAR && p[1] === TEXT) {
if (p[2] === undefined || p[2] === null) p[2] = ''
else if (!p[2]) p[2] = concat('', p[2])
if (Array.isArray(p[2][0])) {
cur[2].push.apply(cur[2], p[2])
} else {
cur[2].push(p[2])
}
} else if (s === TEXT) {
cur[2].push(p[1])
} else if (s === ATTR_EQ || s === ATTR_BREAK) {
// no-op
} else {
throw new Error('unhandled: ' + s)
}
}
if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) {
tree[2].shift()
}
if (tree[2].length > 2
|| (tree[2].length === 2 && /\S/.test(tree[2][1]))) {
throw new Error(
'multiple root elements must be wrapped in an enclosing tag'
)
}
if (Array.isArray(tree[2][0]) && typeof tree[2][0][0] === 'string'
&& Array.isArray(tree[2][0][2])) {
tree[2][0] = h(tree[2][0][0], tree[2][0][1], tree[2][0][2])
}
return tree[2][0]
function parse (str) {
var res = []
if (state === ATTR_VALUE_W) state = ATTR
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i)
if (state === TEXT && c === '<') {
if (reg.length) res.push([TEXT, reg])
reg = ''
state = OPEN
} else if (c === '>' && !quot(state) && state !== COMMENT) {
if (state === OPEN) {
res.push([OPEN,reg])
} else if (state === ATTR_KEY) {
res.push([ATTR_KEY,reg])
} else if (state === ATTR_VALUE && reg.length) {
res.push([ATTR_VALUE,reg])
}
res.push([CLOSE])
reg = ''
state = TEXT
} else if (state === COMMENT && /-$/.test(reg) && c === '-') {
if (opts.comments) {
res.push([ATTR_VALUE,reg.substr(0, reg.length - 1)],[CLOSE])
}
reg = ''
state = TEXT
} else if (state === OPEN && /^!--$/.test(reg)) {
if (opts.comments) {
res.push([OPEN, reg],[ATTR_KEY,'comment'],[ATTR_EQ])
}
reg = c
state = COMMENT
} else if (state === TEXT || state === COMMENT) {
reg += c
} else if (state === OPEN && /\s/.test(c)) {
res.push([OPEN, reg])
reg = ''
state = ATTR
} else if (state === OPEN) {
reg += c
} else if (state === ATTR && /[^\s"'=/]/.test(c)) {
state = ATTR_KEY
reg = c
} else if (state === ATTR && /\s/.test(c)) {
if (reg.length) res.push([ATTR_KEY,reg])
res.push([ATTR_BREAK])
} else if (state === ATTR_KEY && /\s/.test(c)) {
res.push([ATTR_KEY,reg])
reg = ''
state = ATTR_KEY_W
} else if (state === ATTR_KEY && c === '=') {
res.push([ATTR_KEY,reg],[ATTR_EQ])
reg = ''
state = ATTR_VALUE_W
} else if (state === ATTR_KEY) {
reg += c
} else if ((state === ATTR_KEY_W || state === ATTR) && c === '=') {
res.push([ATTR_EQ])
state = ATTR_VALUE_W
} else if ((state === ATTR_KEY_W || state === ATTR) && !/\s/.test(c)) {
res.push([ATTR_BREAK])
if (/[\w-]/.test(c)) {
reg += c
state = ATTR_KEY
} else state = ATTR
} else if (state === ATTR_VALUE_W && c === '"') {
state = ATTR_VALUE_DQ
} else if (state === ATTR_VALUE_W && c === "'") {
state = ATTR_VALUE_SQ
} else if (state === ATTR_VALUE_DQ && c === '"') {
res.push([ATTR_VALUE,reg],[ATTR_BREAK])
reg = ''
state = ATTR
} else if (state === ATTR_VALUE_SQ && c === "'") {
res.push([ATTR_VALUE,reg],[ATTR_BREAK])
reg = ''
state = ATTR
} else if (state === ATTR_VALUE_W && !/\s/.test(c)) {
state = ATTR_VALUE
i--
} else if (state === ATTR_VALUE && /\s/.test(c)) {
res.push([ATTR_VALUE,reg],[ATTR_BREAK])
reg = ''
state = ATTR
} else if (state === ATTR_VALUE || state === ATTR_VALUE_SQ
|| state === ATTR_VALUE_DQ) {
reg += c
}
}
if (state === TEXT && reg.length) {
res.push([TEXT,reg])
reg = ''
} else if (state === ATTR_VALUE && reg.length) {
res.push([ATTR_VALUE,reg])
reg = ''
} else if (state === ATTR_VALUE_DQ && reg.length) {
res.push([ATTR_VALUE,reg])
reg = ''
} else if (state === ATTR_VALUE_SQ && reg.length) {
res.push([ATTR_VALUE,reg])
reg = ''
} else if (state === ATTR_KEY) {
res.push([ATTR_KEY,reg])
reg = ''
}
return res
}
}
function strfn (x) {
if (typeof x === 'function') return x
else if (typeof x === 'string') return x
else if (x && typeof x === 'object') return x
else return concat('', x)
}
}
function quot (state) {
return state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ
}
var hasOwn = Object.prototype.hasOwnProperty
function has (obj, key) { return hasOwn.call(obj, key) }
var closeRE = RegExp('^(' + [
'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed',
'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param',
'source', 'track', 'wbr', '!--',
// SVG TAGS
'animate', 'animateTransform', 'circle', 'cursor', 'desc', 'ellipse',
'feBlend', 'feColorMatrix', 'feComposite',
'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap',
'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR',
'feGaussianBlur', 'feImage', 'feMergeNode', 'feMorphology',
'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile',
'feTurbulence', 'font-face-format', 'font-face-name', 'font-face-uri',
'glyph', 'glyphRef', 'hkern', 'image', 'line', 'missing-glyph', 'mpath',
'path', 'polygon', 'polyline', 'rect', 'set', 'stop', 'tref', 'use', 'view',
'vkern'
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$')
function selfClosing (tag) { return closeRE.test(tag) }
},{"hyperscript-attribute-to-property":7}],9:[function(require,module,exports){
assert.notEqual = notEqual
assert.notOk = notOk
assert.equal = equal
assert.ok = assert
module.exports = assert
function equal (a, b, m) {
assert(a == b, m) // eslint-disable-line eqeqeq
}
function notEqual (a, b, m) {
assert(a != b, m) // eslint-disable-line eqeqeq
}
function notOk (t, m) {
assert(!t, m)
}
function assert (t, m) {
if (!t) throw new Error(m || 'AssertionError')
}
},{}],10:[function(require,module,exports){
var assert = require('assert')
var morph = require('./lib/morph')
var TEXT_NODE = 3
// var DEBUG = false
module.exports = nanomorph
// Morph one tree into another tree
//
// no parent
// -> same: diff and walk children
// -> not same: replace and return
// old node doesn't exist
// -> insert new node
// new node doesn't exist
// -> delete old node
// nodes are not the same
// -> diff nodes and apply patch to old node
// nodes are the same
// -> walk all child nodes and append to old node
function nanomorph (oldTree, newTree) {
// if (DEBUG) {
// console.log(
// 'nanomorph\nold\n %s\nnew\n %s',
// oldTree && oldTree.outerHTML,
// newTree && newTree.outerHTML
// )
// }
assert.equal(typeof oldTree, 'object', 'nanomorph: oldTree should be an object')
assert.equal(typeof newTree, 'object', 'nanomorph: newTree should be an object')
var tree = walk(newTree, oldTree)
// if (DEBUG) console.log('=> morphed\n %s', tree.outerHTML)
return tree
}
// Walk and morph a dom tree
function walk (newNode, oldNode) {
// if (DEBUG) {
// console.log(
// 'walk\nold\n %s\nnew\n %s',
// oldNode && oldNode.outerHTML,
// newNode && newNode.outerHTML
// )
// }
if (!oldNode) {
return newNode
} else if (!newNode) {
return null
} else if (newNode.isSameNode && newNode.isSameNode(oldNode)) {
return oldNode
} else if (newNode.tagName !== oldNode.tagName) {
return newNode
} else {
morph(newNode, oldNode)
updateChildren(newNode, oldNode)
return oldNode
}
}
// Update the children of elements
// (obj, obj) -> null
function updateChildren (newNode, oldNode) {
// if (DEBUG) {
// console.log(
// 'updateChildren\nold\n %s\nnew\n %s',
// oldNode && oldNode.outerHTML,
// newNode && newNode.outerHTML
// )
// }
var oldChild, newChild, morphed, oldMatch
// The offset is only ever increased, and used for [i - offset] in the loop
var offset = 0
for (var i = 0; ; i++) {
oldChild = oldNode.childNodes[i]
newChild = newNode.childNodes[i - offset]
// if (DEBUG) {
// console.log(
// '===\n- old\n %s\n- new\n %s',
// oldChild && oldChild.outerHTML,
// newChild && newChild.outerHTML
// )
// }
// Both nodes are empty, do nothing
if (!oldChild && !newChild) {
break
// There is no new child, remove old
} else if (!newChild) {
oldNode.removeChild(oldChild)
i--
// There is no old child, add new
} else if (!oldChild) {
oldNode.appendChild(newChild)
offset++
// Both nodes are the same, morph
} else if (same(newChild, oldChild)) {
morphed = walk(newChild, oldChild)
if (morphed !== oldChild) {
oldNode.replaceChild(morphed, oldChild)
offset++
}
// Both nodes do not share an ID or a placeholder, try reorder
} else {
oldMatch = null
// Try and find a similar node somewhere in the tree
for (var j = i; j < oldNode.childNodes.length; j++) {
if (same(oldNode.childNodes[j], newChild)) {
oldMatch = oldNode.childNodes[j]
break
}
}
// If there was a node with the same ID or placeholder in the old list
if (oldMatch) {
morphed = walk(newChild, oldMatch)
if (morphed !== oldMatch) offset++
oldNode.insertBefore(morphed, oldChild)
// It's safe to morph two nodes in-place if neither has an ID
} else if (!newChild.id && !oldChild.id) {
morphed = walk(newChild, oldChild)
if (morphed !== oldChild) {
oldNode.replaceChild(morphed, oldChild)
offset++
}
// Insert the node at the index if we couldn't morph or find a matching node
} else {
oldNode.insertBefore(newChild, oldChild)
offset++
}
}
}
}
function same (a, b) {
if (a.id) return a.id === b.id
if (a.isSameNode) return a.isSameNode(b)
if (a.tagName !== b.tagName) return false
if (a.type === TEXT_NODE) return a.nodeValue === b.nodeValue
return false
}
},{"./lib/morph":12,"assert":9}],11:[function(require,module,exports){
module.exports = [
// attribute events (can be set with attributes)
'onclick',
'ondblclick',
'onmousedown',
'onmouseup',
'onmouseover',
'onmousemove',
'onmouseout',
'onmouseenter',
'onmouseleave',
'ontouchcancel',
'ontouchend',
'ontouchmove',
'ontouchstart',
'ondragstart',
'ondrag',
'ondragenter',
'ondragleave',
'ondragover',
'ondrop',
'ondragend',
'onkeydown',
'onkeypress',
'onkeyup',
'onunload',
'onabort',
'onerror',
'onresize',
'onscroll',
'onselect',
'onchange',
'onsubmit',
'onreset',
'onfocus',
'onblur',
'oninput',
// other common events
'oncontextmenu',
'onfocusin',
'onfocusout'
]
},{}],12:[function(require,module,exports){
var events = require('./events')
var eventsLength = events.length
var ELEMENT_NODE = 1
var TEXT_NODE = 3
var COMMENT_NODE = 8
module.exports = morph
// diff elements and apply the resulting patch to the old node
// (obj, obj) -> null
function morph (newNode, oldNode) {
var nodeType = newNode.nodeType
var nodeName = newNode.nodeName
if (nodeType === ELEMENT_NODE) {
copyAttrs(newNode, oldNode)
}
if (nodeType === TEXT_NODE || nodeType === COMMENT_NODE) {
if (oldNode.nodeValue !== newNode.nodeValue) {
oldNode.nodeValue = newNode.nodeValue
}
}
// Some DOM nodes are weird
// https://github.com/patrick-steele-idem/morphdom/blob/master/src/specialElHandlers.js
if (nodeName === 'INPUT') updateInput(newNode, oldNode)
else if (nodeName === 'OPTION') updateOption(newNode, oldNode)
else if (nodeName === 'TEXTAREA') updateTextarea(newNode, oldNode)
copyEvents(newNode, oldNode)
}
function copyAttrs (newNode, oldNode) {
var oldAttrs = oldNode.attributes
var newAttrs = newNode.attributes
var attrNamespaceURI = null
var attrValue = null
var fromValue = null
var attrName = null
var attr = null
for (var i = newAttrs.length - 1; i >= 0; --i) {
attr = newAttrs[i]
attrName = attr.name
attrNamespaceURI = attr.namespaceURI
attrValue = attr.value
if (attrNamespaceURI) {
attrName = attr.localName || attrName
fromValue = oldNode.getAttributeNS(attrNamespaceURI, attrName)
if (fromValue !== attrValue) {
oldNode.setAttributeNS(attrNamespaceURI, attrName, attrValue)
}
} else {
if (!oldNode.hasAttribute(attrName)) {
oldNode.setAttribute(attrName, attrValue)
} else {
fromValue = oldNode.getAttribute(attrName)
if (fromValue !== attrValue) {
// apparently values are always cast to strings, ah well
if (attrValue === 'null' || attrValue === 'undefined') {
oldNode.removeAttribute(attrName)
} else {
oldNode.setAttribute(attrName, attrValue)
}
}
}
}
}
// Remove any extra attributes found on the original DOM element that
// weren't found on the target element.
for (var j = oldAttrs.length - 1; j >= 0; --j) {
attr = oldAttrs[j]
if (attr.specified !== false) {
attrName = attr.name
attrNamespaceURI = attr.namespaceURI
if (attrNamespaceURI) {
attrName = attr.localName || attrName
if (!newNode.hasAttributeNS(attrNamespaceURI, attrName)) {
oldNode.removeAttributeNS(attrNamespaceURI, attrName)
}
} else {
if (!newNode.hasAttributeNS(null, attrName)) {
oldNode.removeAttribute(attrName)
}
}
}
}
}
function copyEvents (newNode, oldNode) {
for (var i = 0; i < eventsLength; i++) {
var ev = events[i]
if (newNode[ev]) { // if new element has a whitelisted attribute
oldNode[ev] = newNode[ev] // update existing element
} else if (oldNode[ev]) { // if existing element has it and new one doesnt
oldNode[ev] = undefined // remove it from existing element
}
}
}
function updateOption (newNode, oldNode) {
updateAttribute(newNode, oldNode, 'selected')
}
// The "value" attribute is special for the <input> element since it sets the
// initial value. Changing the "value" attribute without changing the "value"
// property will have no effect since it is only used to the set the initial
// value. Similar for the "checked" attribute, and "disabled".
function updateInput (newNode, oldNode) {
var newValue = newNode.value
var oldValue = oldNode.value
updateAttribute(newNode, oldNode, 'checked')
updateAttribute(newNode, oldNode, 'disabled')
if (newValue !== oldValue) {
oldNode.setAttribute('value', newValue)
oldNode.value = newValue
}
if (newValue === 'null') {
oldNode.value = ''
oldNode.removeAttribute('value')
}
if (!newNode.hasAttributeNS(null, 'value')) {
oldNode.removeAttribute('value')
} else if (oldNode.type === 'range') {
// this is so elements like slider move their UI thingy
oldNode.value = newValue
}
}
function updateTextarea (newNode, oldNode) {
var newValue = newNode.value
if (newValue !== oldNode.value) {
oldNode.value = newValue
}
if (oldNode.firstChild && oldNode.firstChild.nodeValue !== newValue) {
// Needed for IE. Apparently IE sets the placeholder as the
// node value and vise versa. This ignores an empty update.
if (newValue === '' && oldNode.firstChild.nodeValue === oldNode.placeholder) {
return
}
oldNode.firstChild.nodeValue = newValue
}
}
function updateAttribute (newNode, oldNode, name) {
if (newNode[name] !== oldNode[name]) {
oldNode[name] = newNode[name]
if (newNode[name]) {
oldNode.setAttribute(name, '')
} else {
oldNode.removeAttribute(name)
}
}
}
},{"./events":11}],13:[function(require,module,exports){
/* global MutationObserver */
var document = require('global/document')
var window = require('global/window')
var watch = Object.create(null)
var KEY_ID = 'onloadid' + (new Date() % 9e6).toString(36)
var KEY_ATTR = 'data-' + KEY_ID
var INDEX = 0
if (window && window.MutationObserver) {
var observer = new MutationObserver(function (mutations) {
if (Object.keys(watch).length < 1) return
for (var i = 0; i < mutations.length; i++) {
if (mutations[i].attributeName === KEY_ATTR) {
eachAttr(mutations[i], turnon, turnoff)
continue
}
eachMutation(mutations[i].removedNodes, turnoff)
eachMutation(mutations[i].addedNodes, turnon)
}
})
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeOldValue: true,
attributeFilter: [KEY_ATTR]
})
}
module.exports = function onload (el, on, off, caller) {
on = on || function () {}
off = off || function () {}
el.setAttribute(KEY_ATTR, 'o' + INDEX)
watch['o' + INDEX] = [on, off, 0, caller || onload.caller]
INDEX += 1
return el
}
function turnon (index, el) {
if (watch[index][0] && watch[index][2] === 0) {
watch[index][0](el)
watch[index][2] = 1
}
}
function turnoff (index, el) {
if (watch[index][1] && watch[index][2] === 1) {
watch[index][1](el)
watch[index][2] = 0
}
}
function eachAttr (mutation, on, off) {
var newValue = mutation.target.getAttribute(KEY_ATTR)
if (sameOrigin(mutation.oldValue, newValue)) {
watch[newValue] = watch[mutation.oldValue]
return
}
if (watch[mutation.oldValue]) {
off(mutation.oldValue, mutation.target)
}
if (watch[newValue]) {
on(newValue, mutation.target)
}
}
function sameOrigin (oldValue, newValue) {
if (!oldValue || !newValue) return false
return watch[oldValue][3] === watch[newValue][3]
}
function eachMutation (nodes, fn) {
var keys = Object.keys(watch)
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute(KEY_ATTR)) {
var onloadid = nodes[i].getAttribute(KEY_ATTR)
keys.forEach(function (k) {
if (onloadid === k) {
fn(k, nodes[i])
}
})
}
if (nodes[i].childNodes.length > 0) {
eachMutation(nodes[i].childNodes, fn)
}
}
}
},{"global/document":5,"global/window":6}]},{},[2]);