UNPKG

wasm-metering

Version:

injects metering into webassembly binaries

1,054 lines (944 loc) 31.1 kB
(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){ 'use strict' 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){ 'use strict' 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]);