http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/5aa1517a/packages/weex-legacy-framework/index.js ---------------------------------------------------------------------- diff --git a/packages/weex-legacy-framework/index.js b/packages/weex-legacy-framework/index.js new file mode 100644 index 0000000..a2d9804 --- /dev/null +++ b/packages/weex-legacy-framework/index.js @@ -0,0 +1,5770 @@ +/* 'WEEX VANILLA FRAMEWORK 0.20.6, Build 2017-08-01 19:19. */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.WeexVanillaFramework = global.WeexVanillaFramework || {}))); +}(this, (function (exports) { 'use strict'; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * @fileOverview The api for invoking with "$" prefix + */ + +/** + * @deprecated use $vm instead + * find the vm by id + * Note: there is only one id in whole component + * @param {string} id + * @return {Vm} + */ +function $ (id) { + console.warn('[JS Framework] Vm#$ is deprecated, please use Vm#$vm instead'); + var info = this._ids[id]; + if (info) { + return info.vm + } +} + +/** + * find the element by id + * Note: there is only one id in whole component + * @param {string} id + * @return {Element} + */ +function $el (id) { + var info = this._ids[id]; + if (info) { + return info.el + } +} + +/** + * find the vm of the custom component by id + * Note: there is only one id in whole component + * @param {string} id + * @return {Vm} + */ +function $vm (id) { + var info = this._ids[id]; + if (info) { + return info.vm + } +} + +/** + * Fire when differ rendering finished + * + * @param {Function} fn + */ +function $renderThen (fn) { + var app = this._app; + var differ = app.differ; + return differ.then(function () { + fn(); + }) +} + +/** + * scroll an element specified by id into view, + * moreover specify a number of offset optionally + * @param {string} id + * @param {number} offset + */ +function $scrollTo (id, offset) { + console.warn('[JS Framework] Vm#$scrollTo is deprecated, ' + + 'please use "require(\'@weex-module/dom\')' + + '.scrollTo(el, options)" instead'); + var el = this.$el(id); + if (el) { + var dom = this._app.requireModule('dom'); + dom.scrollToElement(el.ref, { offset: offset }); + } +} + +/** + * perform transition animation on an element specified by id + * @param {string} id + * @param {object} options + * @param {object} options.styles + * @param {object} options.duration(ms) + * @param {object} [options.timingFunction] + * @param {object} [options.delay=0(ms)] + * @param {Function} callback + */ +function $transition (id, options, callback) { + var this$1 = this; + + var el = this.$el(id); + if (el && options && options.styles) { + var animation = this._app.requireModule('animation'); + animation.transition(el.ref, options, function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + this$1._setStyle(el, options.styles); + callback && callback.apply(void 0, args); + }); + } +} + +/** + * get some config + * @return {object} some config for app instance + * @property {string} bundleUrl + * @property {boolean} debug + * @property {object} env + * @property {string} env.weexVersion(ex. 1.0.0) + * @property {string} env.appName(ex. TB/TM) + * @property {string} env.appVersion(ex. 5.0.0) + * @property {string} env.platform(ex. iOS/Android) + * @property {string} env.osVersion(ex. 7.0.0) + * @property {string} env.deviceModel **native only** + * @property {number} env.[deviceWidth=750] + * @property {number} env.deviceHeight + */ +function $getConfig (callback) { + var config = this._app.options; + if (typeof callback === 'function') { + console.warn('[JS Framework] the callback of Vm#$getConfig(callback) is deprecated, ' + + 'this api now can directly RETURN config info.'); + callback(config); + } + return config +} + +/** + * @deprecated + * request network via http protocol + * @param {object} params + * @param {Function} callback + */ +function $sendHttp (params, callback) { + console.warn('[JS Framework] Vm#$sendHttp is deprecated, ' + + 'please use "require(\'@weex-module/stream\')' + + '.sendHttp(params, callback)" instead'); + var stream = this._app.requireModule('stream'); + stream.sendHttp(params, callback); +} + +/** + * @deprecated + * open a url + * @param {string} url + */ +function $openURL (url) { + console.warn('[JS Framework] Vm#$openURL is deprecated, ' + + 'please use "require(\'@weex-module/event\')' + + '.openURL(url)" instead'); + var event = this._app.requireModule('event'); + event.openURL(url); +} + +/** + * @deprecated + * set a title for page + * @param {string} title + */ +function $setTitle (title) { + console.warn('[JS Framework] Vm#$setTitle is deprecated, ' + + 'please use "require(\'@weex-module/pageInfo\')' + + '.setTitle(title)" instead'); + var pageInfo = this._app.requireModule('pageInfo'); + pageInfo.setTitle(title); +} + +/** + * @deprecated use "require('@weex-module/moduleName') instead" + * invoke a native method by specifing the name of module and method + * @param {string} moduleName + * @param {string} methodName + * @param {...*} the rest arguments + */ +function $call (moduleName, methodName) { + var args = [], len = arguments.length - 2; + while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; + + console.warn('[JS Framework] Vm#$call is deprecated, ' + + 'please use "require(\'@weex-module/moduleName\')" instead'); + var module = this._app.requireModule(moduleName); + if (module && module[methodName]) { + module[methodName].apply(module, args); + } +} + + +var methods = Object.freeze({ + $: $, + $el: $el, + $vm: $vm, + $renderThen: $renderThen, + $scrollTo: $scrollTo, + $transition: $transition, + $getConfig: $getConfig, + $sendHttp: $sendHttp, + $openURL: $openURL, + $setTitle: $setTitle, + $call: $call +}); + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Mix properties into target object. + * + * @param {Object} to + * @param {Object} from + */ + +function extend (target) { + var src = [], len = arguments.length - 1; + while ( len-- > 0 ) src[ len ] = arguments[ len + 1 ]; + + /* istanbul ignore else */ + if (typeof Object.assign === 'function') { + Object.assign.apply(Object, [ target ].concat( src )); + } + else { + var first = src.shift(); + for (var key in first) { + target[key] = first[key]; + } + if (src.length) { + extend.apply(void 0, [ target ].concat( src )); + } + } + return target +} + +/** + * Define a property. + * + * @param {Object} obj + * @param {String} key + * @param {*} val + * @param {Boolean} [enumerable] + */ + +function def (obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); +} + +/** + * Remove an item from an array + * + * @param {Array} arr + * @param {*} item + */ + +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. + * + * @param {Object} obj + * @param {String} key + * @return {Boolean} + */ +var hasOwnProperty = Object.prototype.hasOwnProperty; +function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) +} + +/** + * Simple bind, faster than native + * + * @param {Function} fn + * @param {Object} ctx + * @return {Function} + */ + +function bind (fn, ctx) { + return function (a) { + var l = arguments.length; + return l + ? l > 1 + ? fn.apply(ctx, arguments) + : fn.call(ctx, a) + : fn.call(ctx) + } +} + +/** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + * + * @param {*} obj + * @return {Boolean} + */ + +function isObject (obj) { + return obj !== null && typeof obj === 'object' +} + +/** + * Strict object type check. Only returns true + * for plain JavaScript objects. + * + * @param {*} obj + * @return {Boolean} + */ + +var toString = Object.prototype.toString; +var OBJECT_STRING = '[object Object]'; +function isPlainObject (obj) { + return toString.call(obj) === OBJECT_STRING +} + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Check if a string starts with $ or _ + * + * @param {String} str + * @return {Boolean} + */ + +function isReserved (str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F +} + +// can we use __proto__? +var hasProto = '__proto__' in {}; + +var _Set; +/* istanbul ignore next */ +if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) { + // use native Set when available. + _Set = Set; +} +else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = function () { + this.set = Object.create(null); + }; + _Set.prototype.has = function (key) { + return this.set[key] !== undefined + }; + _Set.prototype.add = function (key) { + if (key == null || this.set[key]) { + return + } + this.set[key] = 1; + }; + _Set.prototype.clear = function () { + this.set = Object.create(null); + }; +} + +/** + * Polyfill in iOS7 by native because the JavaScript polyfill has memory problem. + * @return {object} + */ + +function createNewSet () { + /* istanbul ignore next */ + /* eslint-disable */ + if (typeof nativeSet === 'object') { + return nativeSet.create() + } + /* eslint-enable */ + return new _Set() +} + +/** + * Create a cached version of a pure function. + * + * @param {Function} fn + * @return {Function} + */ + + + + + + + +function typof (v) { + var s = Object.prototype.toString.call(v); + return s.substring(8, s.length - 1).toLowerCase() +} + +// weex name rules + +var WEEX_COMPONENT_REG = /^@weex-component\//; +var WEEX_MODULE_REG = /^@weex-module\//; +var NORMAL_MODULE_REG = /^\.{1,2}\//; +var JS_SURFIX_REG = /\.js$/; + +var isWeexComponent = function (name) { return !!name.match(WEEX_COMPONENT_REG); }; +var isWeexModule = function (name) { return !!name.match(WEEX_MODULE_REG); }; +var isNormalModule = function (name) { return !!name.match(NORMAL_MODULE_REG); }; +var isNpmModule = function (name) { return !isWeexComponent(name) && !isWeexModule(name) && !isNormalModule(name); }; + +function removeWeexPrefix (str) { + var result = str.replace(WEEX_COMPONENT_REG, '').replace(WEEX_MODULE_REG, ''); + return result +} + +function removeJSSurfix (str) { + return str.replace(JS_SURFIX_REG, '') +} + +/* eslint-disable */ + + +var uid$1 = 0; + +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + * + * @constructor + */ + +function Dep () { + this.id = uid$1++; + this.subs = []; +} + +// 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(); +} + +function resetTarget () { + Dep.target = null; + targetStack = []; +} + +/** + * Add a directive subscriber. + * + * @param {Directive} sub + */ + +Dep.prototype.addSub = function (sub) { + this.subs.push(sub); +}; + +/** + * Remove a directive subscriber. + * + * @param {Directive} sub + */ + +Dep.prototype.removeSub = function (sub) { + remove(this.subs, sub); +}; + +/** + * Add self as a dependency to the target watcher. + */ + +Dep.prototype.depend = function () { + if (Dep.target) { + Dep.target.addDep(this); + } +}; + +/** + * Notify all subscribers of a new value. + */ + +Dep.prototype.notify = function () { + // stablize the subscriber list first + var subs = this.subs.slice(); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } +}; + +/* eslint-disable */ + + +// import { pushWatcher } from './batcher' +var uid = 0; + +/** + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. + * + * @param {Vue} vm + * @param {String|Function} expOrFn + * @param {Function} cb + * @param {Object} options + * - {Array} filters + * - {Boolean} twoWay + * - {Boolean} deep + * - {Boolean} user + * - {Boolean} sync + * - {Boolean} lazy + * - {Function} [preProcess] + * - {Function} [postProcess] + * @constructor + */ + +function Watcher (vm, expOrFn, cb, options) { + // mix in options + if (options) { + extend(this, options); + } + var isFn = typeof expOrFn === 'function'; + this.vm = vm; + vm._watchers.push(this); + this.expression = expOrFn; + this.cb = cb; + this.id = ++uid; // uid for batching + this.active = true; + this.dirty = this.lazy; // for lazy watchers + this.deps = []; + this.newDeps = []; + this.depIds = createNewSet(); // new Set() + this.newDepIds = createNewSet(); // new Set() + // parse expression for getter + if (isFn) { + this.getter = expOrFn; + } + this.value = this.lazy + ? undefined + : this.get(); + // state for avoiding false triggers for deep and Array + // watchers during vm._digest() + this.queued = this.shallow = false; +} + +/** + * Evaluate the getter, and re-collect dependencies. + */ + +Watcher.prototype.get = function () { + pushTarget(this); + var value = this.getter.call(this.vm, this.vm); + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); + } + popTarget(); + this.cleanupDeps(); + return value +}; + +/** + * Add a dependency to this directive. + * + * @param {Dep} dep + */ + +Watcher.prototype.addDep = function (dep) { + var id = dep.id; + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id); + this.newDeps.push(dep); + if (!this.depIds.has(id)) { + dep.addSub(this); + } + } +}; + +/** + * Clean up for dependency collection. + */ + +Watcher.prototype.cleanupDeps = function () { + var this$1 = this; + + var i = this.deps.length; + while (i--) { + var dep = this$1.deps[i]; + if (!this$1.newDepIds.has(dep.id)) { + dep.removeSub(this$1); + } + } + var tmp = this.depIds; + this.depIds = this.newDepIds; + this.newDepIds = tmp; + this.newDepIds.clear(); + tmp = this.deps; + this.deps = this.newDeps; + this.newDeps = tmp; + this.newDeps.length = 0; +}; + +/** + * Subscriber interface. + * Will be called when a dependency changes. + * + * @param {Boolean} shallow + */ + +Watcher.prototype.update = function (shallow) { + if (this.lazy) { + this.dirty = true; + } else { + this.run(); + } + // } else if (this.sync) { + // this.run() + // } else { + // // if queued, only overwrite shallow with non-shallow, + // // but not the other way around. + // this.shallow = this.queued + // ? shallow + // ? this.shallow + // : false + // : !!shallow + // this.queued = true + // pushWatcher(this) + // } +}; + +/** + * Batcher job interface. + * Will be called by the batcher. + */ + +Watcher.prototype.run = function () { + if (this.active) { + var value = this.get(); + if ( + value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated; but only do so if this is a + // non-shallow update (caused by a vm digest). + ((isObject(value) || this.deep) && !this.shallow) + ) { + // set new value + var oldValue = this.value; + this.value = value; + this.cb.call(this.vm, value, oldValue); + } + this.queued = this.shallow = false; + } +}; + +/** + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. + */ + +Watcher.prototype.evaluate = function () { + this.value = this.get(); + this.dirty = false; +}; + +/** + * Depend on all deps collected by this watcher. + */ + +Watcher.prototype.depend = function () { + var this$1 = this; + + var i = this.deps.length; + while (i--) { + this$1.deps[i].depend(); + } +}; + +/** + * Remove self from all dependencies' subcriber list. + */ + +Watcher.prototype.teardown = function () { + var this$1 = this; + + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed or is performing a v-for + // re-render (the watcher list is then filtered by v-for). + if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { + remove(this.vm._watchers, this); + } + var i = this.deps.length; + while (i--) { + this$1.deps[i].removeSub(this$1); + } + this.active = false; + this.vm = this.cb = this.value = null; + } +}; + +/** + * Recrusively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + * + * @param {*} val + * @param {Set} seen + */ + +var seenObjects = createNewSet(); // new Set() +/* istanbul ignore next */ +function traverse (val, seen) { + var i, keys, isA, isO; + if (!seen) { + seen = seenObjects; + seen.clear(); + } + isA = Array.isArray(val); + isO = isObject(val); + if (isA || isO) { + if (val.__ob__) { + var depId = val.__ob__.dep.id; + if (seen.has(depId)) { + return + } else { + seen.add(depId); + } + } + if (isA) { + i = val.length; + while (i--) { traverse(val[i], seen); } + } else if (isO) { + keys = Object.keys(val); + i = keys.length; + while (i--) { traverse(val[keys[i]], seen); } + } + } +} + +/* eslint-disable */ + + +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 arguments$1 = arguments; + + // avoid leaking arguments: + // http://jsperf.com/closure-with-arguments + var i = arguments.length; + var args = new Array(i); + while (i--) { + args[i] = arguments$1[i]; + } + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + inserted = args; + break + case 'unshift': + inserted = args; + break + case 'splice': + inserted = args.slice(2); + break + } + if (inserted) { ob.observeArray(inserted); } + // notify change + ob.dep.notify(); + return result + }); +}); + +/** + * Swap the element at the given index with a new value + * and emits corresponding event. + * + * @param {Number} index + * @param {*} val + * @return {*} - replaced element + */ + +def( + arrayProto, + '$set', + function $set (index, val) { + if (index >= this.length) { + this.length = index + 1; + } + return this.splice(index, 1, val)[0] + } +); + +/** + * Convenience method to remove the element at given index. + * + * @param {Number} index + * @param {*} val + */ + +def( + arrayProto, + '$remove', + function $remove (index) { + /* istanbul ignore if */ + if (!this.length) { return } + /* istanbul ignore else */ + if (typeof index !== 'number') { + index = this.indexOf(index); + } + /* istanbul ignore else */ + if (index > -1) { + this.splice(index, 1); + } + } +); + +/* eslint-disable */ + + +var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + +/** + * 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. + * + * @param {Array|Object} value + * @constructor + */ + +function Observer (value) { + this.value = value; + this.dep = new Dep(); + def(value, '__ob__', this); + if (Array.isArray(value)) { + var augment = hasProto + ? protoAugment + : copyAugment; + augment(value, arrayMethods, arrayKeys); + this.observeArray(value); + } else { + this.walk(value); + } +} + +// Instance methods + +/** + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. + * + * @param {Object} obj + */ + +Observer.prototype.walk = function (obj) { + var this$1 = this; + + for (var key in obj) { + this$1.convert(key, obj[key]); + } +}; + +/** + * Observe a list of Array items. + * + * @param {Array} items + */ + +Observer.prototype.observeArray = function (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); + } +}; + +/** + * Convert a property into getter/setter so we can emit + * the events when the property is accessed/changed. + * + * @param {String} key + * @param {*} val + */ + +Observer.prototype.convert = function (key, val) { + defineReactive(this.value, key, val); +}; + +/** + * Add an owner vm, so that when $set/$delete mutations + * happen we can notify owner vms to proxy the keys and + * digest the watchers. This is only called when the object + * is observed as an instance's root $data. + * + * @param {Vue} vm + */ + +Observer.prototype.addVm = function (vm) { + (this.vms || (this.vms = [])).push(vm); +}; + +/** + * Remove an owner vm. This is called when the object is + * swapped out as an instance's $data object. + * + * @param {Vue} vm + */ + +/* istanbul ignore next */ +Observer.prototype.removeVm = function (vm) { + remove(this.vms, vm); +}; + +// helpers + +/** + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ + * + * @param {Object|Array} target + * @param {Object} src + */ + +function protoAugment (target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ +} + +/** + * Augment an target Object or Array by defining + * hidden properties. + * + * @param {Object|Array} target + * @param {Object} proto + */ + +/* 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. + * + * @param {*} value + * @param {Vue} [vm] + * @return {Observer|undefined} + * @static + */ + +function observe (value, vm) { + if (!isObject(value)) { + return + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if ( + (Array.isArray(value) || isPlainObject(value)) && + Object.isExtensible(value) && + !value._isVue + ) { + ob = new Observer(value); + } + if (ob && vm) { + ob.addVm(vm); + } + return ob +} + +/** + * Define a reactive property on an Object. + * + * @param {Object} obj + * @param {String} key + * @param {*} val + */ + +function defineReactive (obj, key, val) { + 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 = 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)) { + for (var e = (void 0), i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + } + } + } + return value + }, + set: function reactiveSetter (newVal) { + var value = getter ? getter.call(obj) : val; + if (newVal === value) { + return + } + if (setter) { + setter.call(obj, newVal); + } else { + val = newVal; + } + childOb = 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. + * + * @param {Object} obj + * @param {String} key + * @param {*} val + * @public + */ + +/* istanbul ignore next */ +function set (obj, key, val) { + if (Array.isArray(obj)) { + return obj.splice(key, 1, val) + } + if (hasOwn(obj, key)) { + obj[key] = val; + return + } + if (obj._isVue) { + set(obj._data, key, val); + return + } + var ob = obj.__ob__; + if (!ob) { + obj[key] = val; + return + } + ob.convert(key, val); + ob.dep.notify(); + if (ob.vms) { + var i = ob.vms.length; + while (i--) { + var vm = ob.vms[i]; + proxy(vm, key); + // vm.$forceUpdate() + } + } + return val +} + +/** + * Delete a property and trigger change if necessary. + * + * @param {Object} obj + * @param {String} key + */ + +/* istanbul ignore next */ +function del (obj, key) { + if (!hasOwn(obj, key)) { + return + } + delete obj[key]; + var ob = obj.__ob__; + + if (!ob) { + if (obj._isVue) { + delete obj._data[key]; + // obj.$forceUpdate() + } + return + } + ob.dep.notify(); + if (ob.vms) { + var i = ob.vms.length; + while (i--) { + var vm = ob.vms[i]; + unproxy(vm, key); + // vm.$forceUpdate() + } + } +} + +var KEY_WORDS = ['$index', '$value', '$event']; +function proxy (vm, key) { + if (KEY_WORDS.indexOf(key) > -1 || !isReserved(key)) { + Object.defineProperty(vm, key, { + configurable: true, + enumerable: true, + get: function proxyGetter () { + return vm._data[key] + }, + set: function proxySetter (val) { + vm._data[key] = val; + } + }); + } +} + +/* istanbul ignore next */ +function unproxy (vm, key) { + if (!isReserved(key)) { + delete vm[key]; + } +} + +/* eslint-disable */ + + +function initState (vm) { + vm._watchers = []; + initData(vm); + initComputed(vm); + initMethods(vm); +} + +function initData (vm) { + var data = vm._data; + + if (!isPlainObject(data)) { + data = {}; + } + // proxy data on instance + var keys = Object.keys(data); + var i = keys.length; + while (i--) { + proxy(vm, keys[i]); + } + // observe data + observe(data, vm); +} + +/* istanbul ignore next */ +function noop () { +} + +function initComputed (vm) { + var computed = vm._computed; + if (computed) { + for (var key in computed) { + var userDef = computed[key]; + var def$$1 = { + enumerable: true, + configurable: true + }; + if (typeof userDef === 'function') { + def$$1.get = makeComputedGetter(userDef, vm); + def$$1.set = noop; + } else { + def$$1.get = userDef.get + ? userDef.cache !== false + ? makeComputedGetter(userDef.get, vm) + : bind(userDef.get, vm) + : noop; + def$$1.set = userDef.set + ? bind(userDef.set, vm) + : noop; + } + Object.defineProperty(vm, key, def$$1); + } + } +} + +function makeComputedGetter (getter, owner) { + var watcher = new Watcher(owner, getter, null, { + lazy: true + }); + return function computedGetter () { + if (watcher.dirty) { + watcher.evaluate(); + } + if (Dep.target) { + watcher.depend(); + } + return watcher.value + } +} + +function initMethods (vm) { + var methods = vm._methods; + if (methods) { + for (var key in methods) { + vm[key] = methods[key]; + } + } +} + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// @todo: It should be registered by native from `registerComponents()`. + +var config = { + nativeComponentMap: { + text: true, + image: true, + container: true, + slider: { + type: 'slider', + append: 'tree' + }, + cell: { + type: 'cell', + append: 'tree' + } + } +}; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * @fileOverview + * Directive Parser + */ + +var nativeComponentMap = config.nativeComponentMap; + +var SETTERS = { + attr: 'setAttr', + style: 'setStyle', + event: 'addEvent' +}; + +/** + * apply the native component's options(specified by template.type) + * to the template + */ +function applyNaitveComponentOptions (template) { + var type = template.type; + var options = nativeComponentMap[type]; + + if (typeof options === 'object') { + for (var key in options) { + if (template[key] == null) { + template[key] = options[key]; + } + else if (typof(template[key]) === 'object' && + typof(options[key]) === 'object') { + for (var subkey in options[key]) { + if (template[key][subkey] == null) { + template[key][subkey] = options[key][subkey]; + } + } + } + } + } +} + +/** + * bind all id, attr, classnames, style, events to an element + */ +function bindElement (vm, el, template) { + setId(vm, el, template.id, vm); + setAttr(vm, el, template.attr); + setClass(vm, el, template.classList); + setStyle(vm, el, template.style); + bindEvents(vm, el, template.events); +} + +/** + * bind all props to sub vm and bind all style, events to the root element + * of the sub vm if it doesn't have a replaced multi-node fragment + */ +function bindSubVm (vm, subVm, template, repeatItem) { + subVm = subVm || {}; + template = template || {}; + + var options = subVm._options || {}; + + // bind props + var props = options.props; + + if (Array.isArray(props)) { + props = props.reduce(function (result, value) { + result[value] = true; + return result + }, {}); + } + + mergeProps(repeatItem, props, vm, subVm); + mergeProps(template.attr, props, vm, subVm); +} + +/** + * merge class and styles from vm to sub vm. + */ +function bindSubVmAfterInitialized (vm, subVm, template, target) { + if ( target === void 0 ) target = {}; + + mergeClassStyle(template.classList, vm, subVm); + mergeStyle(template.style, vm, subVm); + + // bind subVm to the target element + if (target.children) { + target.children[target.children.length - 1]._vm = subVm; + } + else { + target._vm = subVm; + } +} + +/** + * Bind props from vm to sub vm and watch their updates. + */ +function mergeProps (target, props, vm, subVm) { + if (!target) { + return + } + var loop = function ( key ) { + if (!props || props[key]) { + var value = target[key]; + if (typeof value === 'function') { + var returnValue = watch(vm, value, function (v) { + subVm[key] = v; + }); + subVm[key] = returnValue; + } + else { + subVm[key] = value; + } + } + }; + + for (var key in target) loop( key ); +} + +/** + * Bind style from vm to sub vm and watch their updates. + */ +function mergeStyle (target, vm, subVm) { + var loop = function ( key ) { + var value = target[key]; + if (typeof value === 'function') { + var returnValue = watch(vm, value, function (v) { + if (subVm._rootEl) { + subVm._rootEl.setStyle(key, v); + } + }); + subVm._rootEl.setStyle(key, returnValue); + } + else { + if (subVm._rootEl) { + subVm._rootEl.setStyle(key, value); + } + } + }; + + for (var key in target) loop( key ); +} + +/** + * Bind class & style from vm to sub vm and watch their updates. + */ +function mergeClassStyle (target, vm, subVm) { + var css = vm._options && vm._options.style || {}; + + /* istanbul ignore if */ + if (!subVm._rootEl) { + return + } + + var className = '@originalRootEl'; + css[className] = subVm._rootEl.classStyle; + + function addClassName (list, name) { + if (typof(list) === 'array') { + list.unshift(name); + } + } + + if (typeof target === 'function') { + var value = watch(vm, target, function (v) { + addClassName(v, className); + setClassStyle(subVm._rootEl, css, v); + }); + addClassName(value, className); + setClassStyle(subVm._rootEl, css, value); + } + else if (target != null) { + addClassName(target, className); + setClassStyle(subVm._rootEl, css, target); + } +} + +/** + * bind id to an element + * each id is unique in a whole vm + */ +function setId (vm, el, id, target) { + var map = Object.create(null); + + Object.defineProperties(map, { + vm: { + value: target, + writable: false, + configurable: false + }, + el: { + get: function () { return el || target._rootEl; }, + configurable: false + } + }); + + if (typeof id === 'function') { + var handler = id; + id = handler.call(vm); + if (id || id === 0) { + vm._ids[id] = map; + } + watch(vm, handler, function (newId) { + if (newId) { + vm._ids[newId] = map; + } + }); + } + else if (id && typeof id === 'string') { + vm._ids[id] = map; + } +} + +/** + * bind attr to an element + */ +function setAttr (vm, el, attr) { + bindDir(vm, el, 'attr', attr); +} + +function setClassStyle (el, css, classList) { + var classStyle = {}; + var length = classList.length; + + var loop = function ( i ) { + var style = css[classList[i]]; + if (style) { + Object.keys(style).forEach(function (key) { + classStyle[key] = style[key]; + }); + } + }; + + for (var i = 0; i < length; i++) loop( i ); + el.setClassStyle(classStyle); +} + +/** + * bind classnames to an element + */ +function setClass (vm, el, classList) { + if (typeof classList !== 'function' && !Array.isArray(classList)) { + return + } + if (Array.isArray(classList) && !classList.length) { + el.setClassStyle({}); + return + } + + var style = vm._options && vm._options.style || {}; + if (typeof classList === 'function') { + var value = watch(vm, classList, function (v) { + setClassStyle(el, style, v); + }); + setClassStyle(el, style, value); + } + else { + setClassStyle(el, style, classList); + } +} + +/** + * bind style to an element + */ +function setStyle (vm, el, style) { + bindDir(vm, el, 'style', style); +} + +/** + * add an event type and handler to an element and generate a dom update + */ +function setEvent (vm, el, type, handler) { + el.addEvent(type, bind(handler, vm)); +} + +/** + * add all events of an element + */ +function bindEvents (vm, el, events) { + if (!events) { + return + } + var keys = Object.keys(events); + var i = keys.length; + while (i--) { + var key = keys[i]; + var handler = events[key]; + if (typeof handler === 'string') { + handler = vm[handler]; + /* istanbul ignore if */ + if (!handler) { + console.warn(("[JS Framework] The event handler \"" + handler + "\" is not defined.")); + } + } + setEvent(vm, el, key, handler); + } +} + +/** + * set a series of members as a kind of an element + * for example: style, attr, ... + * if the value is a function then bind the data changes + */ +function bindDir (vm, el, name, data) { + if (!data) { + return + } + var keys = Object.keys(data); + var i = keys.length; + while (i--) { + var key = keys[i]; + var value = data[key]; + if (typeof value === 'function') { + bindKey(vm, el, name, key, value); + } + else { + el[SETTERS[name]](key, value); + } + } +} + +/** + * bind data changes to a certain key to a name series in an element + */ +function bindKey (vm, el, name, key, calc) { + var methodName = SETTERS[name]; + // watch the calc, and returns a value by calc.call() + var value = watch(vm, calc, function (value) { + function handler () { + el[methodName](key, value); + } + var differ = vm && vm._app && vm._app.differ; + if (differ) { + differ.append('element', el.depth, el.ref, handler); + } + else { + handler(); + } + }); + + el[methodName](key, value); +} + +/** + * watch a calc function and callback if the calc value changes + */ +function watch (vm, calc, callback) { + if (vm._static) { + return calc.call(vm, vm) + } + var watcher = new Watcher(vm, calc, function (value, oldValue) { + /* istanbul ignore if */ + if (typeof value !== 'object' && value === oldValue) { + return + } + callback(value); + }); + + return watcher.value +} + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * @fileOverview Document & Element Helpers. + * + * required: + * Document#: createElement, createComment, getRef + * Element#: appendChild, insertBefore, removeChild, nextSibling + */ + +/** + * Create a body by type + * Using this._app.doc + * + * @param {string} type + */ +function createBody (vm, type) { + var doc = vm._app.doc; + return doc.createBody(type) +} + +/** + * Create an element by type + * Using this._app.doc + * + * @param {string} type + */ +function createElement (vm, type) { + var doc = vm._app.doc; + return doc.createElement(type) +} + +/** + * Create and return a frag block for an element. + * The frag block has a starter, ender and the element itself. + * + * @param {object} element + */ +function createBlock (vm, element) { + var start = createBlockStart(vm); + var end = createBlockEnd(vm); + var blockId = lastestBlockId++; + if (element.element) { + var updateMark = element.updateMark; + if (updateMark) { + if (updateMark.element) { + updateMark = updateMark.end; + } + element.element.insertAfter(end, updateMark); + element.element.insertAfter(start, updateMark); + element.updateMark = end; + } + else { + element.element.insertBefore(start, element.end); + element.element.insertBefore(end, element.end); + } + element = element.element; + } + else { + element.appendChild(start); + element.appendChild(end); + } + return { start: start, end: end, element: element, blockId: blockId } +} + +var lastestBlockId = 1; + +/** + * Create and return a block starter. + * Using this._app.doc + */ +function createBlockStart (vm) { + var doc = vm._app.doc; + var anchor = doc.createComment('start'); + return anchor +} + +/** + * Create and return a block ender. + * Using this._app.doc + */ +function createBlockEnd (vm) { + var doc = vm._app.doc; + var anchor = doc.createComment('end'); + return anchor +} + +/** + * Attach target to a certain dest using appendChild by default. + * If the dest is a frag block then insert before the ender. + * If the target is a frag block then attach the starter and ender in order. + * + * @param {object} target + * @param {object} dest + */ +function attachTarget (vm, target, dest) { + if (dest.element) { + var before = dest.end; + var after = dest.updateMark; + // push new target for watch list update later + if (dest.children) { + dest.children.push(target); + } + // for check repeat case + if (after) { + var signal = moveTarget(vm, target, after); + dest.updateMark = target.element ? target.end : target; + return signal + } + else if (target.element) { + dest.element.insertBefore(target.start, before); + dest.element.insertBefore(target.end, before); + } + else { + return dest.element.insertBefore(target, before) + } + } + else { + if (target.element) { + dest.appendChild(target.start); + dest.appendChild(target.end); + } + else { + return dest.appendChild(target) + } + } +} + +/** + * Move target before a certain element. The target maybe block or element. + * + * @param {object} target + * @param {object} before + */ +function moveTarget (vm, target, after) { + if (target.element) { + return moveBlock(target, after) + } + return moveElement(target, after) +} + +/** + * Move element before a certain element. + * + * @param {object} element + * @param {object} before + */ +function moveElement (element, after) { + var parent = after.parentNode; + if (parent) { + return parent.insertAfter(element, after) + } +} + +/** + * Move all elements of the block before a certain element. + * + * @param {object} fragBlock + * @param {object} before + */ +function moveBlock (fragBlock, after) { + var parent = after.parentNode; + + if (parent) { + var el = fragBlock.start; + var signal; + var group = [el]; + + while (el && el !== fragBlock.end) { + el = el.nextSibling; + group.push(el); + } + + var temp = after; + group.every(function (el) { + signal = parent.insertAfter(el, temp); + temp = el; + return signal !== -1 + }); + + return signal + } +} + +/** + * Remove target from DOM tree. + * If the target is a frag block then call _removeBlock + * + * @param {object} target + */ +function removeTarget (vm, target, preserveBlock) { + if ( preserveBlock === void 0 ) preserveBlock = false; + + if (target.element) { + removeBlock(target, preserveBlock); + } + else { + removeElement(target); + } + if (target._vm) { + target._vm.$emit('hook:destroyed'); + } +} + +/** + * Remove a certain element. + * Using this._app.doc + * + * @param {object} target + */ +function removeElement (target) { + var parent = target.parentNode; + + if (parent) { + parent.removeChild(target); + } +} + +/** + * Remove a frag block. + * The second param decides whether the block self should be removed too. + * + * @param {object} fragBlock + * @param {Boolean} preserveBlock=false + */ +function removeBlock (fragBlock, preserveBlock) { + if ( preserveBlock === void 0 ) preserveBlock = false; + + var result = []; + var el = fragBlock.start.nextSibling; + + while (el && el !== fragBlock.end) { + result.push(el); + el = el.nextSibling; + } + + if (!preserveBlock) { + removeElement(fragBlock.start); + } + result.forEach(function (el) { + removeElement(el); + }); + if (!preserveBlock) { + removeElement(fragBlock.end); + } +} + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * @fileOverview + * ViewModel template parser & data-binding process + */ + +/** + * build() + * compile(template, parentNode) + * if (type is content) create contentNode + * else if (dirs have v-for) foreach -> create context + * -> compile(templateWithoutFor, parentNode): diff(list) onchange + * else if (dirs have v-if) assert + * -> compile(templateWithoutIf, parentNode): toggle(shown) onchange + * else if (type is dynamic) + * -> compile(templateWithoutDynamicType, parentNode): watch(type) onchange + * else if (type is custom) + * addChildVm(vm, parentVm) + * build(externalDirs) + * foreach childNodes -> compile(childNode, template) + * else if (type is native) + * set(dirs): update(id/attr/style/class) onchange + * append(template, parentNode) + * foreach childNodes -> compile(childNode, template) + */ +function build (vm) { + var opt = vm._options || {}; + var template = opt.template || {}; + + if (opt.replace) { + if (template.children && template.children.length === 1) { + compile(vm, template.children[0], vm._parentEl); + } + else { + compile(vm, template.children, vm._parentEl); + } + } + else { + compile(vm, template, vm._parentEl); + } + + console.debug(("[JS Framework] \"ready\" lifecycle in Vm(" + (vm._type) + ")")); + vm.$emit('hook:ready'); + vm._ready = true; +} + +/** + * Generate elements by child or children and append to parent elements. + * Root element info would be merged if has. The first argument may be an array + * if the root element with options.replace has not only one child. + * + * @param {object|array} target + * @param {object} dest + * @param {object} meta + */ +function compile (vm, target, dest, meta) { + var app = vm._app || {}; + + if (app.lastSignal === -1) { + return + } + + if (target.attr && target.attr.hasOwnProperty('static')) { + vm._static = true; + } + + if (targetIsFragment(target)) { + compileFragment(vm, target, dest, meta); + return + } + meta = meta || {}; + if (targetIsContent(target)) { + console.debug('[JS Framework] compile "content" block by', target); + vm._content = createBlock(vm, dest); + return + } + + if (targetNeedCheckRepeat(target, meta)) { + console.debug('[JS Framework] compile "repeat" logic by', target); + if (dest.type === 'document') { + console.warn('[JS Framework] The root element does\'t support `repeat` directive!'); + } + else { + compileRepeat(vm, target, dest); + } + return + } + if (targetNeedCheckShown(target, meta)) { + console.debug('[JS Framework] compile "if" logic by', target); + if (dest.type === 'document') { + console.warn('[JS Framework] The root element does\'t support `if` directive!'); + } + else { + compileShown(vm, target, dest, meta); + } + return + } + var typeGetter = meta.type || target.type; + if (targetNeedCheckType(typeGetter, meta)) { + compileType(vm, target, dest, typeGetter, meta); + return + } + var type = typeGetter; + var component = targetIsComposed(vm, target, type); + if (component) { + console.debug('[JS Framework] compile composed component by', target); + compileCustomComponent(vm, component, target, dest, type, meta); + return + } + console.debug('[JS Framework] compile native component by', target); + compileNativeComponent(vm, target, dest, type); +} + +/** + * Check if target is a fragment (an array). + * + * @param {object} target + * @return {boolean} + */ +function targetIsFragment (target) { + return Array.isArray(target) +} + +/** + * Check if target type is content/slot. + * + * @param {object} target + * @return {boolean} + */ +function targetIsContent (target) { + return target.type === 'content' || target.type === 'slot' +} + +/** + * Check if target need to compile by a list. + * + * @param {object} target + * @param {object} meta + * @return {boolean} + */ +function targetNeedCheckRepeat (target, meta) { + return !meta.hasOwnProperty('repeat') && target.repeat +} + +/** + * Check if target need to compile by a boolean value. + * + * @param {object} target + * @param {object} meta + * @return {boolean} + */ +function targetNeedCheckShown (target, meta) { + return !meta.hasOwnProperty('shown') && target.shown +} + +/** + * Check if target need to compile by a dynamic type. + * + * @param {string|function} typeGetter + * @param {object} meta + * @return {boolean} + */ +function targetNeedCheckType (typeGetter, meta) { + return (typeof typeGetter === 'function') && !meta.hasOwnProperty('type') +} + +/** + * Check if this kind of component is composed. + * + * @param {string} type + * @return {boolean} + */ +function targetIsComposed (vm, target, type) { + var component; + if (vm._app && vm._app.customComponentMap) { + component = vm._app.customComponentMap[type]; + } + if (vm._options && vm._options.components) { + component = vm._options.components[type]; + } + if (target.component) { + component = component || {}; + } + return component +} + +/** + * Compile a list of targets. + * + * @param {object} target + * @param {object} dest + * @param {object} meta + */ +function compileFragment (vm, target, dest, meta) { + var fragBlock = createBlock(vm, dest); + target.forEach(function (child) { + compile(vm, child, fragBlock, meta); + }); +} + +/** + * Compile a target with repeat directive. + * + * @param {object} target + * @param {object} dest + */ +function compileRepeat (vm, target, dest) { + var repeat = target.repeat; + var oldStyle = typeof repeat === 'function'; + var getter = repeat.getter || repeat.expression || repeat; + if (typeof getter !== 'function') { + getter = function () { return [] }; + } + var key = repeat.key || '$index'; + var value = repeat.value || '$value'; + var trackBy = repeat.trackBy || target.trackBy || + (target.attr && target.attr.trackBy); + + var fragBlock = createBlock(vm, dest); + fragBlock.children = []; + fragBlock.data = []; + fragBlock.vms = []; + + bindRepeat(vm, target, fragBlock, { getter: getter, key: key, value: value, trackBy: trackBy, oldStyle: oldStyle }); +} + +/** + * Compile a target with if directive. + * + * @param {object} target + * @param {object} dest + * @param {object} meta + */ +function compileShown (vm, target, dest, meta) { + var newMeta = { shown: true }; + var fragBlock = createBlock(vm, dest); + + if (dest.element && dest.children) { + dest.children.push(fragBlock); + } + + if (meta.repeat) { + newMeta.repeat = meta.repeat; + } + + bindShown(vm, target, fragBlock, newMeta); +} + +/** + * Compile a target with dynamic component type. + * + * @param {object} target + * @param {object} dest + * @param {function} typeGetter + */ +function compileType (vm, target, dest, typeGetter, meta) { + var type = typeGetter.call(vm); + var newMeta = extend({ type: type }, meta); + var fragBlock = createBlock(vm, dest); + + if (dest.element && dest.children) { + dest.children.push(fragBlock); + } + + watch(vm, typeGetter, function (value) { + var newMeta = extend({ type: value }, meta); + removeTarget(vm, fragBlock, true); + compile(vm, target, fragBlock, newMeta); + }); + + compile(vm, target, fragBlock, newMeta); +} + +/** + * Compile a composed component. + * + * @param {object} target + * @param {object} dest + * @param {string} type + */ +function compileCustomComponent (vm, component, target, dest, type, meta) { + var Ctor = vm.constructor; + var subVm = new Ctor(type, component, vm, dest, undefined, { + 'hook:init': function () { + if (vm._static) { + this._static = vm._static; + } + setId(vm, null, target.id, this); + // bind template earlier because of lifecycle issues + this._externalBinding = { + parent: vm, + template: target + }; + }, + 'hook:created': function () { + bindSubVm(vm, this, target, meta.repeat); + }, + 'hook:ready': function () { + if (this._content) { + compileChildren(vm, target, this._content); + } + } + }); + bindSubVmAfterInitialized(vm, subVm, target, dest); +} + +/** + * Generate element from template and attach to the dest if needed. + * The time to attach depends on whether the mode status is node or tree. + * + * @param {object} template + * @param {object} dest + * @param {string} type + */ +function compileNativeComponent (vm, template, dest, type) { + applyNaitveComponentOptions(template); + + var element; + if (dest.ref === '_documentElement') { + // if its parent is documentElement then it's a body + console.debug(("[JS Framework] compile to create body for " + type)); + element = createBody(vm, type); + } + else { + console.debug(("[JS Framework] compile to create element for " + type)); + element = createElement(vm, type); + } + + if (!vm._rootEl) { + vm._rootEl = element; + // bind event earlier because of lifecycle issues + var binding = vm._externalBinding || {}; + var target = binding.template; + var parentVm = binding.parent; + if (target && target.events && parentVm && element) { + for (var type$1 in target.events) { + var handler = parentVm[target.events[type$1]]; + if (handler) { + element.addEvent(type$1, bind(handler, parentVm)); + } + } + } + } + + bindElement(vm, element, template); + + if (template.attr && template.attr.append) { // backward, append prop in attr + template.append = template.attr.append; + } + + if (template.append) { // give the append attribute for ios adaptation + element.attr = element.attr || {}; + element.attr.append = template.append; + } + + var treeMode = template.append === 'tree'; + var app = vm._app || {}; + if (app.lastSignal !== -1 && !treeMode) { + console.debug('[JS Framework] compile to append single node for', element); + app.lastSignal = attachTarget(vm, element, dest); + } + if (app.lastSignal !== -1) { + compileChildren(vm, template, element); + } + if (app.lastSignal !== -1 && treeMode) { + console.debug('[JS Framework] compile to append whole tree for', element); + app.lastSignal = attachTarget(vm, element, dest); + } +} + +/** + * Set all children to a certain parent element. + * + * @param {object} template + * @param {object} dest + */ +function compileChildren (vm, template, dest) { + var app = vm._app || {}; + var children = template.children; + if (children && children.length) { + children.every(function (child) { + compile(vm, child, dest); + return app.lastSignal !== -1 + }); + } +} + +/** + * Watch the list update and refresh the changes. + * + * @param {object} target + * @param {object} fragBlock {vms, data, children} + * @param {object} info {getter, key, value, trackBy, oldStyle} + */ +function bindRepeat (vm, target, fragBlock, info) { + var vms = fragBlock.vms; + var children = fragBlock.children; + var getter = info.getter; + var trackBy = info.trackBy; + var oldStyle = info.oldStyle; + var keyName = info.key; + var valueName = info.value; + + function compileItem (item, index, context) { + var mergedData; + if (oldStyle) { + mergedData = item; + if (isObject(item)) { + mergedData[keyName] = index; + if (!mergedData.hasOwnProperty('INDEX')) { + Object.defineProperty(mergedData, 'INDEX', { + value: function () { + console.warn('[JS Framework] "INDEX" in repeat is deprecated, ' + + 'please use "$index" instead'); + } + }); + } + } + else { + console.warn('[JS Framework] Each list item must be an object in old-style repeat, ' + + 'please use `repeat={{v in list}}` instead.'); + mergedData = {}; + mergedData[keyName] = index; + mergedData[valueName] = item; + } + } + else { + mergedData = {}; + mergedData[keyName] = index; + mergedData[valueName] = item; + } + var newContext = mergeContext(context, mergedData); + vms.push(newContext); + compile(newContext, target, fragBlock, { repeat: item }); + } + + var list = watchBlock(vm, fragBlock, getter, 'repeat', + function (data) { + console.debug('[JS Framework] the "repeat" item has changed', data); + if (!fragBlock || !data) { + return + } + + var oldChildren = children.slice(); + var oldVms = vms.slice(); + var oldData = fragBlock.data.slice(); + // 1. collect all new refs track by + var trackMap = {}; + var reusedMap = {}; + data.forEach(function (item, index) { + var key = trackBy ? item[trackBy] : (oldStyle ? item[keyName] : index); + /* istanbul ignore if */ + if (key == null || key === '') { + return + } + trackMap[key] = item; + }); + + // 2. remove unused element foreach old item + var reusedList = []; + oldData.forEach(function (item, index) { + var key = trackBy ? item[trackBy] : (oldStyle ? item[keyName] : index); + if (trackMap.hasOwnProperty(key)) { + reusedMap[key] = { + item: item, index: index, key: key, + target: oldChildren[index], + vm: oldVms[index] + }; + reusedList.push(item); + } + else { + removeTarget(vm, oldChildren[index]); + } + }); + + // 3. create new element foreach new item + children.length = 0; + vms.length = 0; + fragBlock.data = data.slice(); + fragBlock.updateMark = fragBlock.start; + + data.forEach(function (item, index) { + var key = trackBy ? item[trackBy] : (oldStyle ? item[keyName] : index); + var reused = reusedMap[key]; + if (reused) { + if (reused.item === reusedList[0]) { + reusedList.shift(); + } + else { + reusedList.$remove(reused.item); + moveTarget(vm, reused.target, fragBlock.updateMark, true); + } + children.push(reused.target); + vms.push(reused.vm); + if (oldStyle) { + reused.vm = item; + } + else { + reused.vm[valueName] = item; + } + reused.vm[keyName] = index; + fragBlock.updateMark = reused.target; + } + else { + compileItem(item, index, vm); + } + }); + + delete fragBlock.updateMark; + } + ); + + fragBlock.data = list.slice(0); + list.forEach(function (item, index) { + compileItem(item, index, vm); + }); +} + +/** + * Watch the display update and add/remove the element. + * + * @param {object} target + * @param {object} fragBlock + * @param {object} context + */ +function bindShown (vm, target, fragBlock, meta) { + var display = watchBlock(vm, fragBlock, target.shown, 'shown', + function (display) { + console.debug('[JS Framework] the "if" item was changed', display); + + if (!fragBlock || !!fragBlock.display === !!display) { + return + } + fragBlock.display = !!display; + if (display) { + compile(vm, target, fragBlock, meta); + } + else { + removeTarget(vm, fragBlock, true); + } + } + ); + + fragBlock.display = !!display; + if (display) { + compile(vm, target, fragBlock, meta); + } +} + +/** + * Watch calc value changes and append certain type action to differ. + * It is used for if or repeat data-binding generator. + * + * @param {object} fragBlock + * @param {function} calc + * @param {string} type + * @param {function} handler + * @return {any} init value of calc + */ +function watchBlock (vm, fragBlock, calc, type, handler) { + var differ = vm && vm._app && vm._app.differ; + var config = {}; + var depth = (fragBlock.element.depth || 0) + 1; + + return watch(vm, calc, function (value) { + config.latestValue = value; + if (differ && !config.recorded) { + differ.append(type, depth, fragBlock.blockId, function () { + var latestValue = config.latestValue; + handler(latestValue); + config.recorded = false; + config.latestValue = undefined; + }); + } + config.recorded = true; + }) +} + +/** + * Clone a context and merge certain data. + * + * @param {object} mergedData + * @return {object} + */ +function mergeContext (context, mergedData) { + var newContext = Object.create(context); + newContext._data = mergedData; + initData(newContext); + initComputed(newContext); + newContext._realParent = context; + if (context._static) { + newContext._static = context._static; + } + return newContext +} + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * @fileOverview + * Everything about component event which includes event object, event listener, + * event emitter and lifecycle hooks. + */ + +/** + * Event object definition. An event object has `type`, `timestamp` and + * `detail` from which a component emit. The event object could be dispatched to + * parents or broadcasted to children except `this.stop()` is called. + * @param {string} type + * @param {any} detail + */ +function Evt (type, detail) { + if (detail instanceof Evt) { + return detail + } + + this.timestamp = Date.now(); + this.detail = detail; + this.type = type; + + var shouldStop = false; + + /** + * stop dispatch and broadcast + */ + this.stop = function () { + shouldStop = true; + }; + + /** + * check if it can't be dispatched or broadcasted + */ + this.hasStopped = function () { + return shouldStop + }; +} + +/** + * Emit an event but not broadcast down or dispatch up. + * @param {string} type + * @param {any} detail + */ +function $emit (type, detail) { + var this$1 = this; + + var events = this._vmEvents; + var handlerList = events[type]; + if (handlerList) { + var evt = new Evt(type, detail); + handlerList.forEach(function (handler) { + handler.call(this$1, evt); + }); + } +} + +/** + * Emit an event and dispatch it up. + * @param {string} type + * @param {any} detail + */ +function $dispatch (type, detail) { + var evt = new Evt(type, detail); + this.$emit(type, evt); + + if (!evt.hasStopped() && this._parent && this._parent.$dispatch) { + this._parent.$dispatch(type, evt); + } +} + +/** + * Emit an event and broadcast it down. + * @param {string} type + * @param {any} detail + */ +function $broadcast (type, detail) { + var evt = new Evt(type, detail); + this.$emit(type, evt); + + if (!evt.hasStopped() && this._childrenVms) { + this._childrenVms.forEach(function (subVm) { + subVm.$broadcast(type, evt); + }); + } +} + +/** + * Add event listener. + * @param {string} type + * @param {function} handler + */ +function $on (type, handler) { + if (!type || typeof handler !== 'function') { + return + } + var events = this._vmEvents; + var handlerList = events[type] || []; + handlerList.push(handler); + events[type] = handlerList; + + // fixed old version lifecycle design + /* istanbul ignore if */ + if (type === 'hook:ready' && this._ready) { + this.$emit('hook:ready'); + } +} + +/** + * Remove event listener. + * @param {string} type + * @param {function} handler + */ +function $off (type, handler) { + if (!type) { + return + } + var events = this._vmEvents; + if (!handler) { + delete events[type]; + return + } + var handlerList = events[type]; + if (!handlerList) { + return + } + handlerList.$remove(handler); +} + +var LIFE_CYCLE_TYPES = ['init', 'created', 'ready', 'destroyed']; + +/** + * Init events: + * 1. listen `events` in component options & `externalEvents`. + * 2. bind lifecycle hooks. + * @param {Vm} vm + * @param {object} externalEvents + */ +function initEvents (vm, externalEvents) { + var options = vm._options || {}; + var events = options.events || {}; + for (var type1 in events) { + vm.$on(type1, events[type1]); + } + for (var type2 in externalEvents) { + vm.$on(type2, externalEvents[type2]); + } + LIFE_CYCLE_TYPES.forEach(function (type) { + vm.$on(("hook:" + type), options[type]); + }); +} + +/** + * Bind event related methods to ViewModel instance. + * @param {Vm} vm + */ +function mixinEvents (vm) { + vm.$emit = $emit; + vm.$dispatch = $dispatch; + vm.$broadcast = $broadcast; + vm.$on = $on; + vm.$off = $off; +} + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * @fileOverview + * ViewModel Constructor & definition + */ + +/** + * ViewModel constructor + * + * @param {string} type + * @param {object} options component options + * @param {object} parentVm which contains _app + * @param {object} parentEl root element or frag block + * @param {object} mergedData external data + * @param {object} externalEvents external events + */ +function Vm ( + type, + options, + parentVm, + parentEl, + mergedData, + externalEvents +) { + parentVm = parentVm || {}; + this._parent = parentVm._realParent ? parentVm._realParent : parentVm; + this._app = parentVm._app || {}; + parentVm._childrenVms && parentVm._childrenVms.push(this); + + if (!options && this._app.customComponentMap) { + options = this._app.customComponentMap[type]; + } + options = options || {}; + + var data = options.data || {}; + + this._options = options; + this._methods = options.methods || {}; + this._computed = options.computed || {}; + this._css = options.style || {}; + this._ids = {}; + this._vmEvents = {}; + this._childrenVms = []; + this._type = type; + + // bind events and lifecycles + initEvents(this, externalEvents); + + console.debug(("[JS Framework] \"init\" lifecycle in Vm(" + (this._type) + ")")); + this.$emit('hook:init'); + this._inited = true; + + // proxy data and methods + // observe data and add this to vms + this._data = typeof data === 'function' ? data() : data; + if (mergedData) { + extend(this._data, mergedData); + } + initState(this); + + console.debug(("[JS Framework] \"created\" lifecycle in Vm(" + (this._type) + ")")); + this.$emit('hook:created'); + this._created = true; + + // backward old ready entry + if (options.methods && options.methods.ready) { + console.warn('"exports.methods.ready" is deprecated, ' + + 'please use "exports.created" instead'); + options.methods.ready.call(this); + } + + if (!this._app.doc) { + return + } + + // if no parentElement then specify the documentElement + this._parentEl = parentEl || this._app.doc.documentElement; + build(this); +} + +mixinEvents(Vm.prototype); + +/** + * Watch an function and bind all the data appeared in it. When the related + * data changes, the callback will be called with new value as 1st param. + * + * @param {Function} fn + * @param {Function} callback + */ +Vm.prototype.$watch = function (fn, callback) { + watch(this, fn, callback); +}; + +Vm.set = set; +Vm.delete = del; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var nativeModules = {}; + +// for testing + +/** + * for testing + */ + + +/** + * for testing + */ + + +// for framework + +/** + * init modules for an app instance + * the second param determines whether to replace an existed method + */ +function initModules (modules, ifReplace) { + var loop = function ( moduleName ) { + // init `modules[moduleName][]` + var methods = nativeModules[moduleName]; + if (!methods) { + methods = {}; + nativeModules[moduleName] = methods; + } + + // push each non-existed new method + modules[moduleName].forEach(function (method) { + if (typeof method === 'string') { + method = { + name: method + }; + } + + if (!methods[method.name] || ifReplace) { + methods[method.name] = method; + } + }); + }; + + for (var moduleName in modules) loop( moduleName ); +} + +/** + * init app methods + */ +function initMethods$1 (Vm, apis) { + var p = Vm.prototype; + + for (var apiName in apis) { + if (!p.hasOwnProperty(apiName)) { + p[apiName] = apis[apiName]; + } + } +} + +/** + * get a module of methods for an app instance + */ +function requireModule (app, name) { + var methods = nativeModules[name]; + var target = {}; + var loop = function ( methodName ) { + Object.defineProperty(target, methodName, { + configurable: true, + enumerable: true, + get: function moduleGetter () { + return function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return app.callTasks({ + module: name, + method: methodName, + args: args + }); + } + }, + set: function moduleSetter (value) { + if (typeof value === 'function') { + return app.callTasks({ + module: name, + method: methodName, + args: [value] + }) + } + } + }); + }; + + for (var methodName in methods) loop( methodName ); + return target +} + +/** + * get a custom component options + */ +function requireCustomComponent (app, name) { + var customComponentMap = app.customComponentMap; + return customComponentMap[name] +} + +/** + * register a custom component options + */ +function registerCustomComponent (app, name, def) { + var customComponentMap = app.customComponentMap; + + if (customComponentMap[name]) { + console.error(("[JS Framework] define a component(" + name + ") that already exists")); + return + } + + customComponentMap[name] = def; +} + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var semver = createCommonjsModule(function (module, exports) { +exports = module.exports = SemVer; + +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ false && + /* nomin */ /\bsemver\b/i.test(false)) + /* nomin */ { debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; } +/* nomin */ else + /* nomin */ { debug = function() {}; } + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0'; + +var MAX_LENGTH = 256; +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + +// The actual regexps go on exports.re +var re = exports.re = []; +var src = exports.src = []; +var R = 0; + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++; +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +var NUMERICIDENTIFIERLOOSE = R++; +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++; +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; + + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++; +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')'; + +var MAINVERSIONLOOSE = R++; +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++; +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + +var PRERELEASEIDENTIFIERLOOSE = R++; +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++; +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + +var PRERELEASELOOSE = R++; +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++; +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++; +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; + + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++; +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?'; + +src[FULL] = '^' + FULLPLAIN + '$'; + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?'; + +var LOOSE = R++; +src[LOOSE] = '^' + LOOSEPLAIN + '$'; + +var GTLT = R++; +src[GTLT] = '((?:<|>)?=?)'; + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++; +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; +var XRANGEIDENTIFIER = R++; +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; + +var XRANGEPLAIN = R++; +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?'; + +var XRANGEPLAINLOOSE = R++; +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?'; + +var XRANGE = R++; +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; +var XRANGELOOSE = R++; +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++; +src[LONETILDE] = '(?:~>?)'; + +var TILDETRIM = R++; +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); +var tildeTrimReplace = '$1~'; + +var TILDE = R++; +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; +var TILDELOOSE = R++; +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++; +src[LONECARET] = '(?:\\^)'; + +var CARETTRIM = R++; +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); +var caretTrimReplace = '$1^'; + +var CARET = R++; +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; +var CARETLOOSE = R++; +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++; +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; +var COMPARATOR = R++; +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++; +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); +var comparatorTrimReplace = '$1$2$3'; + + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++; +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$'; + +var HYPHENRANGELOOSE = R++; +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$'; + +// Star ranges basically just allow anything at all. +var STAR = R++; +src[STAR] = '(<|>)?=?\\s*\\*'; + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]); + if (!re[i]) + { re[i] = new RegExp(src[i]); } +} + +exports.parse = parse; +function parse(version, loose) { + if (version instanceof SemVer) + { return version; } + + if (typeof version !== 'string') + { return null; } + + if (version.length > MAX_LENGTH) + { return null; } + + var r = loose ? re[LOOSE] : re[FULL]; + if (!r.test(version)) + { return null; } + + try { + return new SemVer(version, loose); + } catch (er) { + return null; + } +} + +exports.valid = valid; +function valid(version, loose) { + var v = parse(version, loose); + return v ? v.version : null; +} + + +exports.clean = clean; +function clean(version, loose) { + var s = parse(version.trim().replace(/^[=v]+/, ''), loose); + return s ? s.version : null; +} + +exports.SemVer = SemVer; + +function SemVer(version, loose) { + if (version instanceof SemVer) { + if (version.loose === loose) + { return version; } + else + { version = version.version; } + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version); + } + + if (version.length > MAX_LENGTH) + { throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') } + + if (!(this instanceof SemVer)) + { return new SemVer(version, loose); } + + debug('SemVer', version, loose); + this.loose = loose; + var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + + if (!m) + { throw new TypeError('Invalid Version: ' + version); } + + this.raw = version; + + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) + { throw new TypeError('Invalid major version') } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) + { throw new TypeError('Invalid minor version') } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) + { throw new TypeError('Invalid patch version') } + + // numberify any prerelease numeric ids + if (!m[4]) + { this.prerelease = []; } + else + { this.prerelease = m[4].split('.').map(function(id) { + if (/^[0-9]+$/.test(id)) { + var num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) + { return num; } + } + return id; + }); } + + this.build = m[5] ? m[5].split('.') : []; + this.format(); +} + +SemVer.prototype.format = function() { + this.version = this.major + '.' + this.minor + '.' + this.patch; + if (this.prerelease.length) + { this.version += '-' + this.prerelease.join('.'); } + return this.version; +}; + +SemVer.prototype.toString = function() { + return this.version; +}; + +SemVer.prototype.compare = function(other) { + debug('SemVer.compare', this.version, this.loose, other); + if (!(other instanceof SemVer)) + { other = new SemVer(other, this.loose); } + + return this.compareMain(other) || this.comparePre(other); +}; + +SemVer.prototype.compareMain = function(other) { + if (!(other instanceof SemVer)) + { other = new SemVer(other, this.loose); } + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch); +}; + +SemVer.prototype.comparePre = function(other) { + var this$1 = this; + + if (!(other instanceof SemVer)) + { other = new SemVer(other, this.loose); } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) + { return -1; } + else if (!this.prerelease.length && other.prerelease.length) + { return 1; } + else if (!this.prerelease.length && !other.prerelease.length) + { return 0; } + + var i = 0; + do { + var a = this$1.prerelease[i]; + var b = other.prerelease[i]; + debug('prerelease compare', i, a, b); + if (a === undefined && b === undefined) + { return 0; } + else if (b === undefined) + { return 1; } + else if (a === undefined) + { return -1; } + else if (a === b) + { continue; } + else + { return compareIdentifiers(a, b); } + } while (++i); +}; + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function(release, identifier) { + var this$1 = this; + + switch (release) { + case 'premajor': + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc('pre', identifier); + break; + case 'preminor': + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc('pre', identifier); + break; + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0; + this.inc('patch', identifier); + this.inc('pre', identifier); +
<TRUNCATED>