From: Ben Beltran Date: Tue, 29 Aug 2017 03:54:26 +0000 (-0500) Subject: Commit everything hastily X-Git-Url: https://git.r.bdr.sh/rbdr/sorting-hat-renderer/commitdiff_plain/4b3d812031dd07c251623d7155159115e99d2671?ds=sidebyside Commit everything hastily I left evertything until the last minute, so I didn't have a chance to do it nicely. SORRY. --- diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7e2f179 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +assets diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..a088ae1 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,14 @@ +{ + "extends": "eslint-config-hapi", + "rules": { + "indent": [ + 2, + 2 + ], + "no-undef": 2 + }, + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 8 + } +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d6ecb50 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: node_js + +node_js: + - "8" + +script: + - npm run lint + - npm run build diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..050f881 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] +### Added +- JSDoc gerneration +- Eslint config +- Websocket server +- Mindwave integration +- Support for tmnt strategy (default) +- This CHANGELOG +- A Readme + +[Unreleased]: https://github.com/rbdr/sorting-hat/compare/master...develop diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..19270e0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Contributing to Lissajous Renderer + +This app is intended to be part of a short demo for the gdljs community +that uses the mindwave eeg to sort you into a house or ninja turtle +personality. It's not really intended to go beyond that, however if you +would like to contribute and improve it will be appreciated. + +## How to contribute + +Above All: Be nice, always. + +* Ensure the linter shows no warnings or errors +* Don't break the CI +* Make the PRs according to [Git Flow][gitflow]: (features go to + develop, hotfixes go to master) +* Update the CHANGELOG + +[gitflow]: https://github.com/nvie/gitflow diff --git a/README.md b/README.md index b48ac8c..c837b6d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -# sorting-hat-renderer -Frontend for the sorting hat +# Sorting Hat Frontend + +A renderer for the sorting hat, sorts you to a variety of sets based on the +assignment of mind waves. diff --git a/assets/bundle.js b/assets/bundle.js new file mode 100644 index 0000000..4141d10 --- /dev/null +++ b/assets/bundle.js @@ -0,0 +1,9717 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["SortingHat"] = factory(); + else + root["SortingHat"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/assets/"; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 2); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(process, global) {/*! + * Vue.js v2.4.2 + * (c) 2014-2017 Evan You + * Released under the MIT License. + */ +/* */ + +// these helpers produces better vm code in JS engines due to their +// explicitness and function inlining +function isUndef(v) { + return v === undefined || v === null; +} + +function isDef(v) { + return v !== undefined && v !== null; +} + +function isTrue(v) { + return v === true; +} + +function isFalse(v) { + return v === false; +} + +/** + * Check if value is primitive + */ +function isPrimitive(value) { + return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'; +} + +/** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + */ +function isObject(obj) { + return obj !== null && typeof obj === 'object'; +} + +var _toString = Object.prototype.toString; + +/** + * Strict object type check. Only returns true + * for plain JavaScript objects. + */ +function isPlainObject(obj) { + return _toString.call(obj) === '[object Object]'; +} + +function isRegExp(v) { + return _toString.call(v) === '[object RegExp]'; +} + +/** + * Check if val is a valid array index. + */ +function isValidArrayIndex(val) { + var n = parseFloat(val); + return n >= 0 && Math.floor(n) === n && isFinite(val); +} + +/** + * Convert a value to a string that is actually rendered. + */ +function toString(val) { + return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val); +} + +/** + * Convert a input value to a number for persistence. + * If the conversion fails, return original string. + */ +function toNumber(val) { + var n = parseFloat(val); + return isNaN(n) ? val : n; +} + +/** + * Make a map and return a function for checking if a key + * is in that map. + */ +function makeMap(str, expectsLowerCase) { + var map = Object.create(null); + var list = str.split(','); + for (var i = 0; i < list.length; i++) { + map[list[i]] = true; + } + return expectsLowerCase ? function (val) { + return map[val.toLowerCase()]; + } : function (val) { + return map[val]; + }; +} + +/** + * Check if a tag is a built-in tag. + */ +var isBuiltInTag = makeMap('slot,component', true); + +/** + * Check if a attribute is a reserved attribute. + */ +var isReservedAttribute = makeMap('key,ref,slot,is'); + +/** + * Remove an item from an array + */ +function remove(arr, item) { + if (arr.length) { + var index = arr.indexOf(item); + if (index > -1) { + return arr.splice(index, 1); + } + } +} + +/** + * Check whether the object has the property. + */ +var hasOwnProperty = Object.prototype.hasOwnProperty; +function hasOwn(obj, key) { + return hasOwnProperty.call(obj, key); +} + +/** + * Create a cached version of a pure function. + */ +function cached(fn) { + var cache = Object.create(null); + return function cachedFn(str) { + var hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +} + +/** + * Camelize a hyphen-delimited string. + */ +var camelizeRE = /-(\w)/g; +var camelize = cached(function (str) { + return str.replace(camelizeRE, function (_, c) { + return c ? c.toUpperCase() : ''; + }); +}); + +/** + * Capitalize a string. + */ +var capitalize = cached(function (str) { + return str.charAt(0).toUpperCase() + str.slice(1); +}); + +/** + * Hyphenate a camelCase string. + */ +var hyphenateRE = /([^-])([A-Z])/g; +var hyphenate = cached(function (str) { + return str.replace(hyphenateRE, '$1-$2').replace(hyphenateRE, '$1-$2').toLowerCase(); +}); + +/** + * Simple bind, faster than native + */ +function bind(fn, ctx) { + function boundFn(a) { + var l = arguments.length; + return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx); + } + // record original fn length + boundFn._length = fn.length; + return boundFn; +} + +/** + * Convert an Array-like object to a real Array. + */ +function toArray(list, start) { + start = start || 0; + var i = list.length - start; + var ret = new Array(i); + while (i--) { + ret[i] = list[i + start]; + } + return ret; +} + +/** + * Mix properties into target object. + */ +function extend(to, _from) { + for (var key in _from) { + to[key] = _from[key]; + } + return to; +} + +/** + * Merge an Array of Objects into a single Object. + */ +function toObject(arr) { + var res = {}; + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]); + } + } + return res; +} + +/** + * Perform no operation. + * Stubbing args to make Flow happy without leaving useless transpiled code + * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/) + */ +function noop(a, b, c) {} + +/** + * Always return false. + */ +var no = function (a, b, c) { + return false; +}; + +/** + * Return same value + */ +var identity = function (_) { + return _; +}; + +/** + * Generate a static keys string from compiler modules. + */ +function genStaticKeys(modules) { + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []); + }, []).join(','); +} + +/** + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? + */ +function looseEqual(a, b) { + if (a === b) { + return true; + } + var isObjectA = isObject(a); + var isObjectB = isObject(b); + if (isObjectA && isObjectB) { + try { + var isArrayA = Array.isArray(a); + var isArrayB = Array.isArray(b); + if (isArrayA && isArrayB) { + return a.length === b.length && a.every(function (e, i) { + return looseEqual(e, b[i]); + }); + } else if (!isArrayA && !isArrayB) { + var keysA = Object.keys(a); + var keysB = Object.keys(b); + return keysA.length === keysB.length && keysA.every(function (key) { + return looseEqual(a[key], b[key]); + }); + } else { + /* istanbul ignore next */ + return false; + } + } catch (e) { + /* istanbul ignore next */ + return false; + } + } else if (!isObjectA && !isObjectB) { + return String(a) === String(b); + } else { + return false; + } +} + +function looseIndexOf(arr, val) { + for (var i = 0; i < arr.length; i++) { + if (looseEqual(arr[i], val)) { + return i; + } + } + return -1; +} + +/** + * Ensure a function is called only once. + */ +function once(fn) { + var called = false; + return function () { + if (!called) { + called = true; + fn.apply(this, arguments); + } + }; +} + +var SSR_ATTR = 'data-server-rendered'; + +var ASSET_TYPES = ['component', 'directive', 'filter']; + +var LIFECYCLE_HOOKS = ['beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', 'deactivated']; + +/* */ + +var config = { + /** + * Option merge strategies (used in core/util/options) + */ + optionMergeStrategies: Object.create(null), + + /** + * Whether to suppress warnings. + */ + silent: false, + + /** + * Show production mode tip message on boot? + */ + productionTip: process.env.NODE_ENV !== 'production', + + /** + * Whether to enable devtools + */ + devtools: process.env.NODE_ENV !== 'production', + + /** + * Whether to record perf + */ + performance: false, + + /** + * Error handler for watcher errors + */ + errorHandler: null, + + /** + * Warn handler for watcher warns + */ + warnHandler: null, + + /** + * Ignore certain custom elements + */ + ignoredElements: [], + + /** + * Custom user key aliases for v-on + */ + keyCodes: Object.create(null), + + /** + * Check if a tag is reserved so that it cannot be registered as a + * component. This is platform-dependent and may be overwritten. + */ + isReservedTag: no, + + /** + * Check if an attribute is reserved so that it cannot be used as a component + * prop. This is platform-dependent and may be overwritten. + */ + isReservedAttr: no, + + /** + * Check if a tag is an unknown element. + * Platform-dependent. + */ + isUnknownElement: no, + + /** + * Get the namespace of an element + */ + getTagNamespace: noop, + + /** + * Parse the real tag name for the specific platform. + */ + parsePlatformTagName: identity, + + /** + * Check if an attribute must be bound using property, e.g. value + * Platform-dependent. + */ + mustUseProp: no, + + /** + * Exposed for legacy reasons + */ + _lifecycleHooks: LIFECYCLE_HOOKS +}; + +/* */ + +var emptyObject = Object.freeze({}); + +/** + * Check if a string starts with $ or _ + */ +function isReserved(str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F; +} + +/** + * Define a property. + */ +function def(obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); +} + +/** + * Parse simple path. + */ +var bailRE = /[^\w.$]/; +function parsePath(path) { + if (bailRE.test(path)) { + return; + } + var segments = path.split('.'); + return function (obj) { + for (var i = 0; i < segments.length; i++) { + if (!obj) { + return; + } + obj = obj[segments[i]]; + } + return obj; + }; +} + +/* */ + +var warn = noop; +var tip = noop; +var formatComponentName = null; // work around flow check + +if (process.env.NODE_ENV !== 'production') { + var hasConsole = typeof console !== 'undefined'; + var classifyRE = /(?:^|[-_])(\w)/g; + var classify = function (str) { + return str.replace(classifyRE, function (c) { + return c.toUpperCase(); + }).replace(/[-_]/g, ''); + }; + + warn = function (msg, vm) { + var trace = vm ? generateComponentTrace(vm) : ''; + + if (config.warnHandler) { + config.warnHandler.call(null, msg, vm, trace); + } else if (hasConsole && !config.silent) { + console.error("[Vue warn]: " + msg + trace); + } + }; + + tip = function (msg, vm) { + if (hasConsole && !config.silent) { + console.warn("[Vue tip]: " + msg + (vm ? generateComponentTrace(vm) : '')); + } + }; + + formatComponentName = function (vm, includeFile) { + if (vm.$root === vm) { + return ''; + } + var name = typeof vm === 'string' ? vm : typeof vm === 'function' && vm.options ? vm.options.name : vm._isVue ? vm.$options.name || vm.$options._componentTag : vm.name; + + var file = vm._isVue && vm.$options.__file; + if (!name && file) { + var match = file.match(/([^/\\]+)\.vue$/); + name = match && match[1]; + } + + return (name ? "<" + classify(name) + ">" : "") + (file && includeFile !== false ? " at " + file : ''); + }; + + var repeat = function (str, n) { + var res = ''; + while (n) { + if (n % 2 === 1) { + res += str; + } + if (n > 1) { + str += str; + } + n >>= 1; + } + return res; + }; + + var generateComponentTrace = function (vm) { + if (vm._isVue && vm.$parent) { + var tree = []; + var currentRecursiveSequence = 0; + while (vm) { + if (tree.length > 0) { + var last = tree[tree.length - 1]; + if (last.constructor === vm.constructor) { + currentRecursiveSequence++; + vm = vm.$parent; + continue; + } else if (currentRecursiveSequence > 0) { + tree[tree.length - 1] = [last, currentRecursiveSequence]; + currentRecursiveSequence = 0; + } + } + tree.push(vm); + vm = vm.$parent; + } + return '\n\nfound in\n\n' + tree.map(function (vm, i) { + return "" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm) ? formatComponentName(vm[0]) + "... (" + vm[1] + " recursive calls)" : formatComponentName(vm)); + }).join('\n'); + } else { + return "\n\n(found in " + formatComponentName(vm) + ")"; + } + }; +} + +/* */ + +function handleError(err, vm, info) { + if (config.errorHandler) { + config.errorHandler.call(null, err, vm, info); + } else { + if (process.env.NODE_ENV !== 'production') { + warn("Error in " + info + ": \"" + err.toString() + "\"", vm); + } + /* istanbul ignore else */ + if (inBrowser && typeof console !== 'undefined') { + console.error(err); + } else { + throw err; + } + } +} + +/* */ +/* globals MutationObserver */ + +// can we use __proto__? +var hasProto = '__proto__' in {}; + +// Browser environment sniffing +var inBrowser = typeof window !== 'undefined'; +var UA = inBrowser && window.navigator.userAgent.toLowerCase(); +var isIE = UA && /msie|trident/.test(UA); +var isIE9 = UA && UA.indexOf('msie 9.0') > 0; +var isEdge = UA && UA.indexOf('edge/') > 0; +var isAndroid = UA && UA.indexOf('android') > 0; +var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); +var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; + +// Firefix has a "watch" function on Object.prototype... +var nativeWatch = {}.watch; + +var supportsPassive = false; +if (inBrowser) { + try { + var opts = {}; + Object.defineProperty(opts, 'passive', { + get: function get() { + /* istanbul ignore next */ + supportsPassive = true; + } + }); // https://github.com/facebook/flow/issues/285 + window.addEventListener('test-passive', null, opts); + } catch (e) {} +} + +// this needs to be lazy-evaled because vue may be required before +// vue-server-renderer can set VUE_ENV +var _isServer; +var isServerRendering = function () { + if (_isServer === undefined) { + /* istanbul ignore if */ + if (!inBrowser && typeof global !== 'undefined') { + // detect presence of vue-server-renderer and avoid + // Webpack shimming the process + _isServer = global['process'].env.VUE_ENV === 'server'; + } else { + _isServer = false; + } + } + return _isServer; +}; + +// detect devtools +var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + +/* istanbul ignore next */ +function isNative(Ctor) { + return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); +} + +var hasSymbol = typeof Symbol !== 'undefined' && isNative(Symbol) && typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); + +/** + * Defer a task to execute it asynchronously. + */ +var nextTick = function () { + var callbacks = []; + var pending = false; + var timerFunc; + + function nextTickHandler() { + pending = false; + var copies = callbacks.slice(0); + callbacks.length = 0; + for (var i = 0; i < copies.length; i++) { + copies[i](); + } + } + + // the nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: + /* istanbul ignore if */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + var logError = function (err) { + console.error(err); + }; + timerFunc = function () { + p.then(nextTickHandler).catch(logError); + // in problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { + setTimeout(noop); + } + }; + } else if (typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]')) { + // use MutationObserver where native Promise is not available, + // e.g. PhantomJS IE11, iOS7, Android 4.4 + var counter = 1; + var observer = new MutationObserver(nextTickHandler); + var textNode = document.createTextNode(String(counter)); + observer.observe(textNode, { + characterData: true + }); + timerFunc = function () { + counter = (counter + 1) % 2; + textNode.data = String(counter); + }; + } else { + // fallback to setTimeout + /* istanbul ignore next */ + timerFunc = function () { + setTimeout(nextTickHandler, 0); + }; + } + + return function queueNextTick(cb, ctx) { + var _resolve; + callbacks.push(function () { + if (cb) { + try { + cb.call(ctx); + } catch (e) { + handleError(e, ctx, 'nextTick'); + } + } else if (_resolve) { + _resolve(ctx); + } + }); + if (!pending) { + pending = true; + timerFunc(); + } + if (!cb && typeof Promise !== 'undefined') { + return new Promise(function (resolve, reject) { + _resolve = resolve; + }); + } + }; +}(); + +var _Set; +/* istanbul ignore if */ +if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set; +} else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = function () { + function Set() { + this.set = Object.create(null); + } + Set.prototype.has = function has(key) { + return this.set[key] === true; + }; + Set.prototype.add = function add(key) { + this.set[key] = true; + }; + Set.prototype.clear = function clear() { + this.set = Object.create(null); + }; + + return Set; + }(); +} + +/* */ + +var uid = 0; + +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ +var Dep = function Dep() { + this.id = uid++; + this.subs = []; +}; + +Dep.prototype.addSub = function addSub(sub) { + this.subs.push(sub); +}; + +Dep.prototype.removeSub = function removeSub(sub) { + remove(this.subs, sub); +}; + +Dep.prototype.depend = function depend() { + if (Dep.target) { + Dep.target.addDep(this); + } +}; + +Dep.prototype.notify = function notify() { + // stabilize the subscriber list first + var subs = this.subs.slice(); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } +}; + +// the current target watcher being evaluated. +// this is globally unique because there could be only one +// watcher being evaluated at any time. +Dep.target = null; +var targetStack = []; + +function pushTarget(_target) { + if (Dep.target) { + targetStack.push(Dep.target); + } + Dep.target = _target; +} + +function popTarget() { + Dep.target = targetStack.pop(); +} + +/* + * not type checking this file because flow doesn't play well with + * dynamically accessing methods on Array prototype + */ + +var arrayProto = Array.prototype; +var arrayMethods = Object.create(arrayProto);['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) { + // cache original method + var original = arrayProto[method]; + def(arrayMethods, method, function mutator() { + var args = [], + len = arguments.length; + while (len--) args[len] = arguments[len]; + + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + case 'unshift': + inserted = args; + break; + case 'splice': + inserted = args.slice(2); + break; + } + if (inserted) { + ob.observeArray(inserted); + } + // notify change + ob.dep.notify(); + return result; + }); +}); + +/* */ + +var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + +/** + * By default, when a reactive property is set, the new value is + * also converted to become reactive. However when passing down props, + * we don't want to force conversion because the value may be a nested value + * under a frozen data structure. Converting it would defeat the optimization. + */ +var observerState = { + shouldConvert: true +}; + +/** + * Observer class that are attached to each observed + * object. Once attached, the observer converts target + * object's property keys into getter/setters that + * collect dependencies and dispatches updates. + */ +var Observer = function Observer(value) { + this.value = value; + this.dep = new Dep(); + this.vmCount = 0; + def(value, '__ob__', this); + if (Array.isArray(value)) { + var augment = hasProto ? protoAugment : copyAugment; + augment(value, arrayMethods, arrayKeys); + this.observeArray(value); + } else { + this.walk(value); + } +}; + +/** + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. + */ +Observer.prototype.walk = function walk(obj) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i], obj[keys[i]]); + } +}; + +/** + * Observe a list of Array items. + */ +Observer.prototype.observeArray = function observeArray(items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); + } +}; + +// helpers + +/** + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ + */ +function protoAugment(target, src, keys) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ +} + +/** + * Augment an target Object or Array by defining + * hidden properties. + */ +/* istanbul ignore next */ +function copyAugment(target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); + } +} + +/** + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. + */ +function observe(value, asRootData) { + if (!isObject(value)) { + return; + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if (observerState.shouldConvert && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) { + ob = new Observer(value); + } + if (asRootData && ob) { + ob.vmCount++; + } + return ob; +} + +/** + * Define a reactive property on an Object. + */ +function defineReactive$$1(obj, key, val, customSetter, shallow) { + var dep = new Dep(); + + var property = Object.getOwnPropertyDescriptor(obj, key); + if (property && property.configurable === false) { + return; + } + + // cater for pre-defined getter/setters + var getter = property && property.get; + var setter = property && property.set; + + var childOb = !shallow && observe(val); + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter() { + var value = getter ? getter.call(obj) : val; + if (Dep.target) { + dep.depend(); + if (childOb) { + childOb.dep.depend(); + } + if (Array.isArray(value)) { + dependArray(value); + } + } + return value; + }, + set: function reactiveSetter(newVal) { + var value = getter ? getter.call(obj) : val; + /* eslint-disable no-self-compare */ + if (newVal === value || newVal !== newVal && value !== value) { + return; + } + /* eslint-enable no-self-compare */ + if (process.env.NODE_ENV !== 'production' && customSetter) { + customSetter(); + } + if (setter) { + setter.call(obj, newVal); + } else { + val = newVal; + } + childOb = !shallow && observe(newVal); + dep.notify(); + } + }); +} + +/** + * Set a property on an object. Adds the new property and + * triggers change notification if the property doesn't + * already exist. + */ +function set(target, key, val) { + if (Array.isArray(target) && isValidArrayIndex(key)) { + target.length = Math.max(target.length, key); + target.splice(key, 1, val); + return val; + } + if (hasOwn(target, key)) { + target[key] = val; + return val; + } + var ob = target.__ob__; + if (target._isVue || ob && ob.vmCount) { + process.env.NODE_ENV !== 'production' && warn('Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.'); + return val; + } + if (!ob) { + target[key] = val; + return val; + } + defineReactive$$1(ob.value, key, val); + ob.dep.notify(); + return val; +} + +/** + * Delete a property and trigger change if necessary. + */ +function del(target, key) { + if (Array.isArray(target) && isValidArrayIndex(key)) { + target.splice(key, 1); + return; + } + var ob = target.__ob__; + if (target._isVue || ob && ob.vmCount) { + process.env.NODE_ENV !== 'production' && warn('Avoid deleting properties on a Vue instance or its root $data ' + '- just set it to null.'); + return; + } + if (!hasOwn(target, key)) { + return; + } + delete target[key]; + if (!ob) { + return; + } + ob.dep.notify(); +} + +/** + * Collect dependencies on array elements when the array is touched, since + * we cannot intercept array element access like property getters. + */ +function dependArray(value) { + for (var e = void 0, i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + if (Array.isArray(e)) { + dependArray(e); + } + } +} + +/* */ + +/** + * Option overwriting strategies are functions that handle + * how to merge a parent option value and a child option + * value into the final value. + */ +var strats = config.optionMergeStrategies; + +/** + * Options with restrictions + */ +if (process.env.NODE_ENV !== 'production') { + strats.el = strats.propsData = function (parent, child, vm, key) { + if (!vm) { + warn("option \"" + key + "\" can only be used during instance " + 'creation with the `new` keyword.'); + } + return defaultStrat(parent, child); + }; +} + +/** + * Helper that recursively merges two data objects together. + */ +function mergeData(to, from) { + if (!from) { + return to; + } + var key, toVal, fromVal; + var keys = Object.keys(from); + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + toVal = to[key]; + fromVal = from[key]; + if (!hasOwn(to, key)) { + set(to, key, fromVal); + } else if (isPlainObject(toVal) && isPlainObject(fromVal)) { + mergeData(toVal, fromVal); + } + } + return to; +} + +/** + * Data + */ +function mergeDataOrFn(parentVal, childVal, vm) { + if (!vm) { + // in a Vue.extend merge, both should be functions + if (!childVal) { + return parentVal; + } + if (!parentVal) { + return childVal; + } + // when parentVal & childVal are both present, + // we need to return a function that returns the + // merged result of both functions... no need to + // check if parentVal is a function here because + // it has to be a function to pass previous merges. + return function mergedDataFn() { + return mergeData(typeof childVal === 'function' ? childVal.call(this) : childVal, typeof parentVal === 'function' ? parentVal.call(this) : parentVal); + }; + } else if (parentVal || childVal) { + return function mergedInstanceDataFn() { + // instance merge + var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal; + var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined; + if (instanceData) { + return mergeData(instanceData, defaultData); + } else { + return defaultData; + } + }; + } +} + +strats.data = function (parentVal, childVal, vm) { + if (!vm) { + if (childVal && typeof childVal !== 'function') { + process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); + + return parentVal; + } + return mergeDataOrFn.call(this, parentVal, childVal); + } + + return mergeDataOrFn(parentVal, childVal, vm); +}; + +/** + * Hooks and props are merged as arrays. + */ +function mergeHook(parentVal, childVal) { + return childVal ? parentVal ? parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal] : parentVal; +} + +LIFECYCLE_HOOKS.forEach(function (hook) { + strats[hook] = mergeHook; +}); + +/** + * Assets + * + * When a vm is present (instance creation), we need to do + * a three-way merge between constructor options, instance + * options and parent options. + */ +function mergeAssets(parentVal, childVal) { + var res = Object.create(parentVal || null); + return childVal ? extend(res, childVal) : res; +} + +ASSET_TYPES.forEach(function (type) { + strats[type + 's'] = mergeAssets; +}); + +/** + * Watchers. + * + * Watchers hashes should not overwrite one + * another, so we merge them as arrays. + */ +strats.watch = function (parentVal, childVal) { + // work around Firefox's Object.prototype.watch... + if (parentVal === nativeWatch) { + parentVal = undefined; + } + if (childVal === nativeWatch) { + childVal = undefined; + } + /* istanbul ignore if */ + if (!childVal) { + return Object.create(parentVal || null); + } + if (!parentVal) { + return childVal; + } + var ret = {}; + extend(ret, parentVal); + for (var key in childVal) { + var parent = ret[key]; + var child = childVal[key]; + if (parent && !Array.isArray(parent)) { + parent = [parent]; + } + ret[key] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child]; + } + return ret; +}; + +/** + * Other object hashes. + */ +strats.props = strats.methods = strats.inject = strats.computed = function (parentVal, childVal) { + if (!parentVal) { + return childVal; + } + var ret = Object.create(null); + extend(ret, parentVal); + if (childVal) { + extend(ret, childVal); + } + return ret; +}; +strats.provide = mergeDataOrFn; + +/** + * Default strategy. + */ +var defaultStrat = function (parentVal, childVal) { + return childVal === undefined ? parentVal : childVal; +}; + +/** + * Validate component names + */ +function checkComponents(options) { + for (var key in options.components) { + var lower = key.toLowerCase(); + if (isBuiltInTag(lower) || config.isReservedTag(lower)) { + warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key); + } + } +} + +/** + * Ensure all props option syntax are normalized into the + * Object-based format. + */ +function normalizeProps(options) { + var props = options.props; + if (!props) { + return; + } + var res = {}; + var i, val, name; + if (Array.isArray(props)) { + i = props.length; + while (i--) { + val = props[i]; + if (typeof val === 'string') { + name = camelize(val); + res[name] = { type: null }; + } else if (process.env.NODE_ENV !== 'production') { + warn('props must be strings when using array syntax.'); + } + } + } else if (isPlainObject(props)) { + for (var key in props) { + val = props[key]; + name = camelize(key); + res[name] = isPlainObject(val) ? val : { type: val }; + } + } + options.props = res; +} + +/** + * Normalize all injections into Object-based format + */ +function normalizeInject(options) { + var inject = options.inject; + if (Array.isArray(inject)) { + var normalized = options.inject = {}; + for (var i = 0; i < inject.length; i++) { + normalized[inject[i]] = inject[i]; + } + } +} + +/** + * Normalize raw function directives into object format. + */ +function normalizeDirectives(options) { + var dirs = options.directives; + if (dirs) { + for (var key in dirs) { + var def = dirs[key]; + if (typeof def === 'function') { + dirs[key] = { bind: def, update: def }; + } + } + } +} + +/** + * Merge two option objects into a new one. + * Core utility used in both instantiation and inheritance. + */ +function mergeOptions(parent, child, vm) { + if (process.env.NODE_ENV !== 'production') { + checkComponents(child); + } + + if (typeof child === 'function') { + child = child.options; + } + + normalizeProps(child); + normalizeInject(child); + normalizeDirectives(child); + var extendsFrom = child.extends; + if (extendsFrom) { + parent = mergeOptions(parent, extendsFrom, vm); + } + if (child.mixins) { + for (var i = 0, l = child.mixins.length; i < l; i++) { + parent = mergeOptions(parent, child.mixins[i], vm); + } + } + var options = {}; + var key; + for (key in parent) { + mergeField(key); + } + for (key in child) { + if (!hasOwn(parent, key)) { + mergeField(key); + } + } + function mergeField(key) { + var strat = strats[key] || defaultStrat; + options[key] = strat(parent[key], child[key], vm, key); + } + return options; +} + +/** + * Resolve an asset. + * This function is used because child instances need access + * to assets defined in its ancestor chain. + */ +function resolveAsset(options, type, id, warnMissing) { + /* istanbul ignore if */ + if (typeof id !== 'string') { + return; + } + var assets = options[type]; + // check local registration variations first + if (hasOwn(assets, id)) { + return assets[id]; + } + var camelizedId = camelize(id); + if (hasOwn(assets, camelizedId)) { + return assets[camelizedId]; + } + var PascalCaseId = capitalize(camelizedId); + if (hasOwn(assets, PascalCaseId)) { + return assets[PascalCaseId]; + } + // fallback to prototype chain + var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; + if (process.env.NODE_ENV !== 'production' && warnMissing && !res) { + warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id, options); + } + return res; +} + +/* */ + +function validateProp(key, propOptions, propsData, vm) { + var prop = propOptions[key]; + var absent = !hasOwn(propsData, key); + var value = propsData[key]; + // handle boolean props + if (isType(Boolean, prop.type)) { + if (absent && !hasOwn(prop, 'default')) { + value = false; + } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) { + value = true; + } + } + // check default value + if (value === undefined) { + value = getPropDefaultValue(vm, prop, key); + // since the default value is a fresh copy, + // make sure to observe it. + var prevShouldConvert = observerState.shouldConvert; + observerState.shouldConvert = true; + observe(value); + observerState.shouldConvert = prevShouldConvert; + } + if (process.env.NODE_ENV !== 'production') { + assertProp(prop, key, value, vm, absent); + } + return value; +} + +/** + * Get the default value of a prop. + */ +function getPropDefaultValue(vm, prop, key) { + // no default, return undefined + if (!hasOwn(prop, 'default')) { + return undefined; + } + var def = prop.default; + // warn against non-factory defaults for Object & Array + if (process.env.NODE_ENV !== 'production' && isObject(def)) { + warn('Invalid default value for prop "' + key + '": ' + 'Props with type Object/Array must use a factory function ' + 'to return the default value.', vm); + } + // the raw prop value was also undefined from previous render, + // return previous default value to avoid unnecessary watcher trigger + if (vm && vm.$options.propsData && vm.$options.propsData[key] === undefined && vm._props[key] !== undefined) { + return vm._props[key]; + } + // call factory function for non-Function types + // a value is Function if its prototype is function even across different execution context + return typeof def === 'function' && getType(prop.type) !== 'Function' ? def.call(vm) : def; +} + +/** + * Assert whether a prop is valid. + */ +function assertProp(prop, name, value, vm, absent) { + if (prop.required && absent) { + warn('Missing required prop: "' + name + '"', vm); + return; + } + if (value == null && !prop.required) { + return; + } + var type = prop.type; + var valid = !type || type === true; + var expectedTypes = []; + if (type) { + if (!Array.isArray(type)) { + type = [type]; + } + for (var i = 0; i < type.length && !valid; i++) { + var assertedType = assertType(value, type[i]); + expectedTypes.push(assertedType.expectedType || ''); + valid = assertedType.valid; + } + } + if (!valid) { + warn('Invalid prop: type check failed for prop "' + name + '".' + ' Expected ' + expectedTypes.map(capitalize).join(', ') + ', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.', vm); + return; + } + var validator = prop.validator; + if (validator) { + if (!validator(value)) { + warn('Invalid prop: custom validator check failed for prop "' + name + '".', vm); + } + } +} + +var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/; + +function assertType(value, type) { + var valid; + var expectedType = getType(type); + if (simpleCheckRE.test(expectedType)) { + valid = typeof value === expectedType.toLowerCase(); + } else if (expectedType === 'Object') { + valid = isPlainObject(value); + } else if (expectedType === 'Array') { + valid = Array.isArray(value); + } else { + valid = value instanceof type; + } + return { + valid: valid, + expectedType: expectedType + }; +} + +/** + * Use function string name to check built-in types, + * because a simple equality check will fail when running + * across different vms / iframes. + */ +function getType(fn) { + var match = fn && fn.toString().match(/^\s*function (\w+)/); + return match ? match[1] : ''; +} + +function isType(type, fn) { + if (!Array.isArray(fn)) { + return getType(fn) === getType(type); + } + for (var i = 0, len = fn.length; i < len; i++) { + if (getType(fn[i]) === getType(type)) { + return true; + } + } + /* istanbul ignore next */ + return false; +} + +/* */ + +var mark; +var measure; + +if (process.env.NODE_ENV !== 'production') { + var perf = inBrowser && window.performance; + /* istanbul ignore if */ + if (perf && perf.mark && perf.measure && perf.clearMarks && perf.clearMeasures) { + mark = function (tag) { + return perf.mark(tag); + }; + measure = function (name, startTag, endTag) { + perf.measure(name, startTag, endTag); + perf.clearMarks(startTag); + perf.clearMarks(endTag); + perf.clearMeasures(name); + }; + } +} + +/* not type checking this file because flow doesn't play well with Proxy */ + +var initProxy; + +if (process.env.NODE_ENV !== 'production') { + var allowedGlobals = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify + ); + + var warnNonPresent = function (target, key) { + warn("Property or method \"" + key + "\" is not defined on the instance but " + "referenced during render. Make sure to declare reactive data " + "properties in the data option.", target); + }; + + var hasProxy = typeof Proxy !== 'undefined' && Proxy.toString().match(/native code/); + + if (hasProxy) { + var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta'); + config.keyCodes = new Proxy(config.keyCodes, { + set: function set(target, key, value) { + if (isBuiltInModifier(key)) { + warn("Avoid overwriting built-in modifier in config.keyCodes: ." + key); + return false; + } else { + target[key] = value; + return true; + } + } + }); + } + + var hasHandler = { + has: function has(target, key) { + var has = key in target; + var isAllowed = allowedGlobals(key) || key.charAt(0) === '_'; + if (!has && !isAllowed) { + warnNonPresent(target, key); + } + return has || !isAllowed; + } + }; + + var getHandler = { + get: function get(target, key) { + if (typeof key === 'string' && !(key in target)) { + warnNonPresent(target, key); + } + return target[key]; + } + }; + + initProxy = function initProxy(vm) { + if (hasProxy) { + // determine which proxy handler to use + var options = vm.$options; + var handlers = options.render && options.render._withStripped ? getHandler : hasHandler; + vm._renderProxy = new Proxy(vm, handlers); + } else { + vm._renderProxy = vm; + } + }; +} + +/* */ + +var VNode = function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) { + this.tag = tag; + this.data = data; + this.children = children; + this.text = text; + this.elm = elm; + this.ns = undefined; + this.context = context; + this.functionalContext = undefined; + this.key = data && data.key; + this.componentOptions = componentOptions; + this.componentInstance = undefined; + this.parent = undefined; + this.raw = false; + this.isStatic = false; + this.isRootInsert = true; + this.isComment = false; + this.isCloned = false; + this.isOnce = false; + this.asyncFactory = asyncFactory; + this.asyncMeta = undefined; + this.isAsyncPlaceholder = false; +}; + +var prototypeAccessors = { child: {} }; + +// DEPRECATED: alias for componentInstance for backwards compat. +/* istanbul ignore next */ +prototypeAccessors.child.get = function () { + return this.componentInstance; +}; + +Object.defineProperties(VNode.prototype, prototypeAccessors); + +var createEmptyVNode = function (text) { + if (text === void 0) text = ''; + + var node = new VNode(); + node.text = text; + node.isComment = true; + return node; +}; + +function createTextVNode(val) { + return new VNode(undefined, undefined, undefined, String(val)); +} + +// optimized shallow clone +// used for static nodes and slot nodes because they may be reused across +// multiple renders, cloning them avoids errors when DOM manipulations rely +// on their elm reference. +function cloneVNode(vnode) { + var cloned = new VNode(vnode.tag, vnode.data, vnode.children, vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory); + cloned.ns = vnode.ns; + cloned.isStatic = vnode.isStatic; + cloned.key = vnode.key; + cloned.isComment = vnode.isComment; + cloned.isCloned = true; + return cloned; +} + +function cloneVNodes(vnodes) { + var len = vnodes.length; + var res = new Array(len); + for (var i = 0; i < len; i++) { + res[i] = cloneVNode(vnodes[i]); + } + return res; +} + +/* */ + +var normalizeEvent = cached(function (name) { + var passive = name.charAt(0) === '&'; + name = passive ? name.slice(1) : name; + var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first + name = once$$1 ? name.slice(1) : name; + var capture = name.charAt(0) === '!'; + name = capture ? name.slice(1) : name; + return { + name: name, + once: once$$1, + capture: capture, + passive: passive + }; +}); + +function createFnInvoker(fns) { + function invoker() { + var arguments$1 = arguments; + + var fns = invoker.fns; + if (Array.isArray(fns)) { + var cloned = fns.slice(); + for (var i = 0; i < cloned.length; i++) { + cloned[i].apply(null, arguments$1); + } + } else { + // return handler return value for single handlers + return fns.apply(null, arguments); + } + } + invoker.fns = fns; + return invoker; +} + +function updateListeners(on, oldOn, add, remove$$1, vm) { + var name, cur, old, event; + for (name in on) { + cur = on[name]; + old = oldOn[name]; + event = normalizeEvent(name); + if (isUndef(cur)) { + process.env.NODE_ENV !== 'production' && warn("Invalid handler for event \"" + event.name + "\": got " + String(cur), vm); + } else if (isUndef(old)) { + if (isUndef(cur.fns)) { + cur = on[name] = createFnInvoker(cur); + } + add(event.name, cur, event.once, event.capture, event.passive); + } else if (cur !== old) { + old.fns = cur; + on[name] = old; + } + } + for (name in oldOn) { + if (isUndef(on[name])) { + event = normalizeEvent(name); + remove$$1(event.name, oldOn[name], event.capture); + } + } +} + +/* */ + +function mergeVNodeHook(def, hookKey, hook) { + var invoker; + var oldHook = def[hookKey]; + + function wrappedHook() { + hook.apply(this, arguments); + // important: remove merged hook to ensure it's called only once + // and prevent memory leak + remove(invoker.fns, wrappedHook); + } + + if (isUndef(oldHook)) { + // no existing hook + invoker = createFnInvoker([wrappedHook]); + } else { + /* istanbul ignore if */ + if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { + // already a merged invoker + invoker = oldHook; + invoker.fns.push(wrappedHook); + } else { + // existing plain hook + invoker = createFnInvoker([oldHook, wrappedHook]); + } + } + + invoker.merged = true; + def[hookKey] = invoker; +} + +/* */ + +function extractPropsFromVNodeData(data, Ctor, tag) { + // we are only extracting raw values here. + // validation and default values are handled in the child + // component itself. + var propOptions = Ctor.options.props; + if (isUndef(propOptions)) { + return; + } + var res = {}; + var attrs = data.attrs; + var props = data.props; + if (isDef(attrs) || isDef(props)) { + for (var key in propOptions) { + var altKey = hyphenate(key); + if (process.env.NODE_ENV !== 'production') { + var keyInLowerCase = key.toLowerCase(); + if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) { + tip("Prop \"" + keyInLowerCase + "\" is passed to component " + formatComponentName(tag || Ctor) + ", but the declared prop name is" + " \"" + key + "\". " + "Note that HTML attributes are case-insensitive and camelCased " + "props need to use their kebab-case equivalents when using in-DOM " + "templates. You should probably use \"" + altKey + "\" instead of \"" + key + "\"."); + } + } + checkProp(res, props, key, altKey, true) || checkProp(res, attrs, key, altKey, false); + } + } + return res; +} + +function checkProp(res, hash, key, altKey, preserve) { + if (isDef(hash)) { + if (hasOwn(hash, key)) { + res[key] = hash[key]; + if (!preserve) { + delete hash[key]; + } + return true; + } else if (hasOwn(hash, altKey)) { + res[key] = hash[altKey]; + if (!preserve) { + delete hash[altKey]; + } + return true; + } + } + return false; +} + +/* */ + +// The template compiler attempts to minimize the need for normalization by +// statically analyzing the template at compile time. +// +// For plain HTML markup, normalization can be completely skipped because the +// generated render function is guaranteed to return Array. There are +// two cases where extra normalization is needed: + +// 1. When the children contains components - because a functional component +// may return an Array instead of a single root. In this case, just a simple +// normalization is needed - if any child is an Array, we flatten the whole +// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep +// because functional components already normalize their own children. +function simpleNormalizeChildren(children) { + for (var i = 0; i < children.length; i++) { + if (Array.isArray(children[i])) { + return Array.prototype.concat.apply([], children); + } + } + return children; +} + +// 2. When the children contains constructs that always generated nested Arrays, +// e.g.