UNPKG

vue-server-renderer

Version:
1,614 lines (1,583 loc) 277 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var stream = require('stream'); var he = require('he'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var he__default = /*#__PURE__*/_interopDefaultLegacy(he); const emptyObject = Object.freeze({}); const isArray = Array.isArray; // These helpers produce 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' || // $flow-disable-line typeof value === 'symbol' || typeof value === 'boolean'); } function isFunction(value) { return typeof value === 'function'; } /** * 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'; } /** * Get the raw type string of a value, e.g., [object Object]. */ const _toString = Object.prototype.toString; function toRawType(value) { return _toString.call(value).slice(8, -1); } /** * Strict object type check. Only returns true * for plain JavaScript objects. */ function isPlainObject(obj) { return _toString.call(obj) === '[object Object]'; } /** * Check if val is a valid array index. */ function isValidArrayIndex(val) { const n = parseFloat(String(val)); return n >= 0 && Math.floor(n) === n && isFinite(val); } function isPromise(val) { return (isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function'); } /** * Convert a value to a string that is actually rendered. */ function toString(val) { return val == null ? '' : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) ? JSON.stringify(val, replacer, 2) : String(val); } function replacer(_key, val) { // avoid circular deps from v3 if (val && val.__v_isRef) { return val.value; } return val; } /** * Convert an input value to a number for persistence. * If the conversion fails, return original string. */ function toNumber(val) { const 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) { const map = Object.create(null); const list = str.split(','); for (let i = 0; i < list.length; i++) { map[list[i]] = true; } return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val]; } /** * Check if a tag is a built-in tag. */ const isBuiltInTag = makeMap('slot,component', true); /** * Check if an attribute is a reserved attribute. */ const isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); /** * Check whether an object has the property. */ const hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn(obj, key) { return hasOwnProperty.call(obj, key); } /** * Create a cached version of a pure function. */ function cached(fn) { const cache = Object.create(null); return function cachedFn(str) { const hit = cache[str]; return hit || (cache[str] = fn(str)); }; } /** * Camelize a hyphen-delimited string. */ const camelizeRE = /-(\w)/g; const camelize = cached((str) => { return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); }); /** * Capitalize a string. */ const capitalize = cached((str) => { return str.charAt(0).toUpperCase() + str.slice(1); }); /** * Hyphenate a camelCase string. */ const hyphenateRE = /\B([A-Z])/g; const hyphenate = cached((str) => { return str.replace(hyphenateRE, '-$1').toLowerCase(); }); /** * Mix properties into target object. */ function extend(to, _from) { for (const key in _from) { to[key] = _from[key]; } return to; } /** * Merge an Array of Objects into a single Object. */ function toObject(arr) { const res = {}; for (let i = 0; i < arr.length; i++) { if (arr[i]) { extend(res, arr[i]); } } return res; } /* eslint-disable no-unused-vars */ /** * 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$1(a, b, c) { } /** * Always return false. */ const no = (a, b, c) => false; /* eslint-enable no-unused-vars */ /** * Return the same value. */ const identity = (_) => _; /** * Generate a string containing static keys from compiler modules. */ function genStaticKeys(modules) { return modules .reduce((keys, m) => 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; const isObjectA = isObject(a); const isObjectB = isObject(b); if (isObjectA && isObjectB) { try { const isArrayA = Array.isArray(a); const isArrayB = Array.isArray(b); if (isArrayA && isArrayB) { return (a.length === b.length && a.every((e, i) => { return looseEqual(e, b[i]); })); } else if (a instanceof Date && b instanceof Date) { return a.getTime() === b.getTime(); } else if (!isArrayA && !isArrayB) { const keysA = Object.keys(a); const keysB = Object.keys(b); return (keysA.length === keysB.length && keysA.every(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; } } /** * Return the first index at which a loosely equal value can be * found in the array (if value is a plain object, the array must * contain an object of the same shape), or -1 if it is not present. */ function looseIndexOf(arr, val) { for (let i = 0; i < arr.length; i++) { if (looseEqual(arr[i], val)) return i; } return -1; } // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#polyfill function hasChanged(x, y) { if (x === y) { return x === 0 && 1 / x !== 1 / y; } else { return x === x || y === y; } } const isAttr = makeMap('accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' + 'checked,cite,class,code,codebase,color,cols,colspan,content,' + 'contenteditable,contextmenu,controls,coords,data,datetime,default,' + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,for,' + 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' + 'target,title,usemap,value,width,wrap'); const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/; // eslint-disable-line no-control-regex const isSSRUnsafeAttr = (name) => { return unsafeAttrCharRE.test(name); }; /* istanbul ignore next */ const isRenderableAttr = (name) => { return (isAttr(name) || name.indexOf('data-') === 0 || name.indexOf('aria-') === 0); }; const propsToAttrMap = { acceptCharset: 'accept-charset', className: 'class', htmlFor: 'for', httpEquiv: 'http-equiv' }; const ESC = { '<': '&lt;', '>': '&gt;', '"': '&quot;', '&': '&amp;' }; function escape(s) { return s.replace(/[<>"&]/g, escapeChar); } function escapeChar(a) { return ESC[a] || a; } const noUnitNumericStyleProps = { 'animation-iteration-count': true, 'border-image-outset': true, 'border-image-slice': true, 'border-image-width': true, 'box-flex': true, 'box-flex-group': true, 'box-ordinal-group': true, 'column-count': true, columns: true, flex: true, 'flex-grow': true, 'flex-positive': true, 'flex-shrink': true, 'flex-negative': true, 'flex-order': true, 'grid-row': true, 'grid-row-end': true, 'grid-row-span': true, 'grid-row-start': true, 'grid-column': true, 'grid-column-end': true, 'grid-column-span': true, 'grid-column-start': true, 'font-weight': true, 'line-clamp': true, 'line-height': true, opacity: true, order: true, orphans: true, 'tab-size': true, widows: true, 'z-index': true, zoom: true, // SVG 'fill-opacity': true, 'flood-opacity': true, 'stop-opacity': true, 'stroke-dasharray': true, 'stroke-dashoffset': true, 'stroke-miterlimit': true, 'stroke-opacity': true, 'stroke-width': true }; const isJS = (file) => /\.js(\?[^.]+)?$/.test(file); const isCSS = (file) => /\.css(\?[^.]+)?$/.test(file); function createPromiseCallback() { let resolve, reject; const promise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; }); const cb = (err, res) => { if (err) return reject(err); resolve(res || ''); }; return { promise, cb }; } // these are reserved for web because they are directly compiled away // during template compilation makeMap('style,class'); // attributes that should be using props for binding const acceptValue = makeMap('input,textarea,option,select,progress'); const mustUseProp = (tag, type, attr) => { return ((attr === 'value' && acceptValue(tag) && type !== 'button') || (attr === 'selected' && tag === 'option') || (attr === 'checked' && tag === 'input') || (attr === 'muted' && tag === 'video')); }; const isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck'); const isValidContentEditableValue = makeMap('events,caret,typing,plaintext-only'); const convertEnumeratedValue = (key, value) => { return isFalsyAttrValue(value) || value === 'false' ? 'false' : // allow arbitrary string value for contenteditable key === 'contenteditable' && isValidContentEditableValue(value) ? value : 'true'; }; const isBooleanAttr = makeMap('allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' + 'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' + 'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' + 'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' + 'required,reversed,scoped,seamless,selected,sortable,' + 'truespeed,typemustmatch,visible'); const isFalsyAttrValue = (val) => { return val == null || val === false; }; function renderAttrs$1(node) { let attrs = node.data.attrs; let res = ''; const opts = node.parent && node.parent.componentOptions; if (isUndef(opts) || opts.Ctor.options.inheritAttrs !== false) { let parent = node.parent; while (isDef(parent)) { // Stop fallthrough in case parent has inheritAttrs option set to false if (parent.componentOptions && parent.componentOptions.Ctor.options.inheritAttrs === false) { break; } if (isDef(parent.data) && isDef(parent.data.attrs)) { attrs = extend(extend({}, attrs), parent.data.attrs); } parent = parent.parent; } } if (isUndef(attrs)) { return res; } for (const key in attrs) { if (isSSRUnsafeAttr(key)) { continue; } if (key === 'style') { // leave it to the style module continue; } res += renderAttr(key, attrs[key]); } return res; } function renderAttr(key, value) { if (isBooleanAttr(key)) { if (!isFalsyAttrValue(value)) { return ` ${key}="${key}"`; } } else if (isEnumeratedAttr(key)) { return ` ${key}="${escape(convertEnumeratedValue(key, value))}"`; } else if (!isFalsyAttrValue(value)) { return ` ${key}="${escape(String(value))}"`; } return ''; } /** * @internal */ class VNode { constructor(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.fnContext = undefined; this.fnOptions = undefined; this.fnScopeId = 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; } // DEPRECATED: alias for componentInstance for backwards compat. /* istanbul ignore next */ get child() { return this.componentInstance; } } const createEmptyVNode = (text = '') => { const 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) { const cloned = new VNode(vnode.tag, vnode.data, // #7975 // clone children array to avoid mutating original in case of cloning // a child. vnode.children && vnode.children.slice(), 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.fnContext = vnode.fnContext; cloned.fnOptions = vnode.fnOptions; cloned.fnScopeId = vnode.fnScopeId; cloned.asyncMeta = vnode.asyncMeta; cloned.isCloned = true; return cloned; } function renderDOMProps$1(node) { let props = node.data.domProps; let res = ''; let parent = node.parent; while (isDef(parent)) { if (parent.data && parent.data.domProps) { props = extend(extend({}, props), parent.data.domProps); } parent = parent.parent; } if (isUndef(props)) { return res; } const attrs = node.data.attrs; for (const key in props) { if (key === 'innerHTML') { setText(node, props[key], true); } else if (key === 'textContent') { setText(node, props[key], false); } else if (key === 'value' && node.tag === 'textarea') { setText(node, toString(props[key]), false); } else { // $flow-disable-line (WTF?) const attr = propsToAttrMap[key] || key.toLowerCase(); if (isRenderableAttr(attr) && // avoid rendering double-bound props/attrs twice !(isDef(attrs) && isDef(attrs[attr]))) { res += renderAttr(attr, props[key]); } } } return res; } function setText(node, text, raw) { const child = new VNode(undefined, undefined, undefined, text); child.raw = raw; node.children = [child]; } /** * unicode letters used for parsing html tags, component names and property paths. * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname * skipping \u10000-\uEFFFF due to it freezing up PhantomJS */ const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; /** * Define a property. */ function def(obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } // can we use __proto__? const hasProto = '__proto__' in {}; // Browser environment sniffing const inBrowser = typeof window !== 'undefined'; const UA = inBrowser && window.navigator.userAgent.toLowerCase(); const isIE = UA && /msie|trident/.test(UA); UA && UA.indexOf('msie 9.0') > 0; const isEdge = UA && UA.indexOf('edge/') > 0; UA && UA.indexOf('android') > 0; UA && /iphone|ipad|ipod|ios/.test(UA); UA && /chrome\/\d+/.test(UA) && !isEdge; UA && /phantomjs/.test(UA); UA && UA.match(/firefox\/(\d+)/); // Firefox has a "watch" function on Object.prototype... // @ts-expect-error firebox support const nativeWatch = {}.watch; let supportsPassive = false; if (inBrowser) { try { const opts = {}; Object.defineProperty(opts, 'passive', { 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 let _isServer; const isServerRendering = () => { 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'] && global['process'].env.VUE_ENV === 'server'; } else { _isServer = false; } } return _isServer; }; /* istanbul ignore next */ function isNative(Ctor) { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); } const hasSymbol = typeof Symbol !== 'undefined' && isNative(Symbol) && typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); let _Set; // $flow-disable-line /* 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 = class Set { constructor() { this.set = Object.create(null); } has(key) { return this.set[key] === true; } add(key) { this.set[key] = true; } clear() { this.set = Object.create(null); } }; } const SSR_ATTR = 'data-server-rendered'; const ASSET_TYPES = ['component', 'directive', 'filter']; const LIFECYCLE_HOOKS = [ 'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', 'deactivated', 'errorCaptured', 'serverPrefetch', 'renderTracked', 'renderTriggered' ]; var config = { /** * Option merge strategies (used in core/util/options) */ // $flow-disable-line optionMergeStrategies: Object.create(null), /** * Whether to suppress warnings. */ silent: false, /** * Show production mode tip message on boot? */ productionTip: true, /** * Whether to enable devtools */ devtools: true, /** * 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 */ // $flow-disable-line 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$1, /** * 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, /** * Perform updates asynchronously. Intended to be used by Vue Test Utils * This will significantly reduce performance if set to false. */ async: true, /** * Exposed for legacy reasons */ _lifecycleHooks: LIFECYCLE_HOOKS }; let currentInstance = null; /** * @internal */ function setCurrentInstance(vm = null) { if (!vm) currentInstance && currentInstance._scope.off(); currentInstance = vm; vm && vm._scope.on(); } /* not type checking this file because flow doesn't play well with Proxy */ { makeMap('Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + 'require' // for Webpack/Browserify ); const hasProxy = typeof Proxy !== 'undefined' && isNative(Proxy); if (hasProxy) { const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); config.keyCodes = new Proxy(config.keyCodes, { set(target, key, value) { if (isBuiltInModifier(key)) { warn$2(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`); return false; } else { target[key] = value; return true; } } }); } } let uid = 0; /** * A dep is an observable that can have multiple * directives subscribing to it. * @internal */ class Dep { constructor() { // pending subs cleanup this._pending = false; this.id = uid++; this.subs = []; } addSub(sub) { this.subs.push(sub); } removeSub(sub) { // #12696 deps with massive amount of subscribers are extremely slow to // clean up in Chromium // to workaround this, we unset the sub for now, and clear them on // next scheduler flush. this.subs[this.subs.indexOf(sub)] = null; if (!this._pending) { this._pending = true; } } depend(info) { if (Dep.target) { Dep.target.addDep(this); if (info && Dep.target.onTrack) { Dep.target.onTrack(Object.assign({ effect: Dep.target }, info)); } } } notify(info) { // stabilize the subscriber list first const subs = this.subs.filter(s => s); for (let i = 0, l = subs.length; i < l; i++) { const sub = subs[i]; if (info) { sub.onTrigger && sub.onTrigger(Object.assign({ effect: subs[i] }, info)); } sub.update(); } } } // The current target watcher being evaluated. // This is globally unique because only one watcher // can be evaluated at a time. Dep.target = null; const targetStack = []; function pushTarget(target) { targetStack.push(target); Dep.target = target; } function popTarget() { targetStack.pop(); Dep.target = targetStack[targetStack.length - 1]; } /* * not type checking this file because flow doesn't play well with * dynamically accessing methods on Array prototype */ const arrayProto = Array.prototype; const arrayMethods = Object.create(arrayProto); const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ]; /** * Intercept mutating methods and emit events */ methodsToPatch.forEach(function (method) { // cache original method const original = arrayProto[method]; def(arrayMethods, method, function mutator(...args) { const result = original.apply(this, args); const ob = this.__ob__; let 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({ type: "array mutation" /* TriggerOpTypes.ARRAY_MUTATION */, target: this, key: method }); } return result; }); }); const arrayKeys = Object.getOwnPropertyNames(arrayMethods); const NO_INITIAL_VALUE = {}; /** * In some cases we may want to disable observation inside a component's * update computation. */ let shouldObserve = true; function toggleObserving(value) { shouldObserve = value; } // ssr mock dep const mockDep = { notify: noop$1, depend: noop$1, addSub: noop$1, removeSub: noop$1 }; /** * Observer class that is attached to each observed * object. Once attached, the observer converts the target * object's property keys into getter/setters that * collect dependencies and dispatch updates. */ class Observer { constructor(value, shallow = false, mock = false) { this.value = value; this.shallow = shallow; this.mock = mock; // this.value = value this.dep = mock ? mockDep : new Dep(); this.vmCount = 0; def(value, '__ob__', this); if (isArray(value)) { if (!mock) { if (hasProto) { value.__proto__ = arrayMethods; /* eslint-enable no-proto */ } else { for (let i = 0, l = arrayKeys.length; i < l; i++) { const key = arrayKeys[i]; def(value, key, arrayMethods[key]); } } } if (!shallow) { this.observeArray(value); } } else { /** * Walk through all properties and convert them into * getter/setters. This method should only be called when * value type is Object. */ const keys = Object.keys(value); for (let i = 0; i < keys.length; i++) { const key = keys[i]; defineReactive(value, key, NO_INITIAL_VALUE, undefined, shallow, mock); } } } /** * Observe a list of Array items. */ observeArray(value) { for (let i = 0, l = value.length; i < l; i++) { observe(value[i], false, this.mock); } } } // helpers /** * 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, shallow, ssrMockReactivity) { if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { return value.__ob__; } if (shouldObserve && (ssrMockReactivity || !isServerRendering()) && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value.__v_skip /* ReactiveFlags.SKIP */ && !isRef(value) && !(value instanceof VNode)) { return new Observer(value, shallow, ssrMockReactivity); } } /** * Define a reactive property on an Object. */ function defineReactive(obj, key, val, customSetter, shallow, mock, observeEvenIfShallow = false) { const dep = new Dep(); const property = Object.getOwnPropertyDescriptor(obj, key); if (property && property.configurable === false) { return; } // cater for pre-defined getter/setters const getter = property && property.get; const setter = property && property.set; if ((!getter || setter) && (val === NO_INITIAL_VALUE || arguments.length === 2)) { val = obj[key]; } let childOb = shallow ? val && val.__ob__ : observe(val, false, mock); Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter() { const value = getter ? getter.call(obj) : val; if (Dep.target) { { dep.depend({ target: obj, type: "get" /* TrackOpTypes.GET */, key }); } if (childOb) { childOb.dep.depend(); if (isArray(value)) { dependArray(value); } } } return isRef(value) && !shallow ? value.value : value; }, set: function reactiveSetter(newVal) { const value = getter ? getter.call(obj) : val; if (!hasChanged(value, newVal)) { return; } if (customSetter) { customSetter(); } if (setter) { setter.call(obj, newVal); } else if (getter) { // #7981: for accessor properties without setter return; } else if (!shallow && isRef(value) && !isRef(newVal)) { value.value = newVal; return; } else { val = newVal; } childOb = shallow ? newVal && newVal.__ob__ : observe(newVal, false, mock); { dep.notify({ type: "set" /* TriggerOpTypes.SET */, target: obj, key, newValue: newVal, oldValue: value }); } } }); return dep; } function set(target, key, val) { if ((isUndef(target) || isPrimitive(target))) { warn$2(`Cannot set reactive property on undefined, null, or primitive value: ${target}`); } if (isReadonly(target)) { warn$2(`Set operation on key "${key}" failed: target is readonly.`); return; } const ob = target.__ob__; if (isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); // when mocking for SSR, array methods are not hijacked if (ob && !ob.shallow && ob.mock) { observe(val, false, true); } return val; } if (key in target && !(key in Object.prototype)) { target[key] = val; return val; } if (target._isVue || (ob && ob.vmCount)) { warn$2('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(ob.value, key, val, undefined, ob.shallow, ob.mock); { ob.dep.notify({ type: "add" /* TriggerOpTypes.ADD */, target: target, key, newValue: val, oldValue: undefined }); } return val; } /** * Collect dependencies on array elements when the array is touched, since * we cannot intercept array element access like property getters. */ function dependArray(value) { for (let e, i = 0, l = value.length; i < l; i++) { e = value[i]; if (e && e.__ob__) { e.__ob__.dep.depend(); } if (isArray(e)) { dependArray(e); } } } function isReadonly(value) { return !!(value && value.__v_isReadonly); } function isRef(r) { return !!(r && r.__v_isRef === true); } const normalizeEvent = cached((name) => { const passive = name.charAt(0) === '&'; name = passive ? name.slice(1) : name; const once = name.charAt(0) === '~'; // Prefixed last, checked first name = once ? name.slice(1) : name; const capture = name.charAt(0) === '!'; name = capture ? name.slice(1) : name; return { name, once, capture, passive }; }); function createFnInvoker(fns, vm) { function invoker() { const fns = invoker.fns; if (isArray(fns)) { const cloned = fns.slice(); for (let i = 0; i < cloned.length; i++) { invokeWithErrorHandling(cloned[i], null, arguments, vm, `v-on handler`); } } else { // return handler return value for single handlers return invokeWithErrorHandling(fns, null, arguments, vm, `v-on handler`); } } invoker.fns = fns; return invoker; } function updateListeners(on, oldOn, add, remove, createOnceHandler, vm) { let name, cur, old, event; for (name in on) { cur = on[name]; old = oldOn[name]; event = normalizeEvent(name); if (isUndef(cur)) { warn$2(`Invalid handler for event "${event.name}": got ` + String(cur), vm); } else if (isUndef(old)) { if (isUndef(cur.fns)) { cur = on[name] = createFnInvoker(cur, vm); } if (isTrue(event.once)) { cur = on[name] = createOnceHandler(event.name, cur, event.capture); } add(event.name, cur, event.capture, event.passive, event.params); } else if (cur !== old) { old.fns = cur; on[name] = old; } } for (name in oldOn) { if (isUndef(on[name])) { event = normalizeEvent(name); remove(event.name, oldOn[name], event.capture); } } } function extractPropsFromVNodeData(data, Ctor, tag) { // we are only extracting raw values here. // validation and default values are handled in the child // component itself. const propOptions = Ctor.options.props; if (isUndef(propOptions)) { return; } const res = {}; const { attrs, props } = data; if (isDef(attrs) || isDef(props)) { for (const key in propOptions) { const altKey = hyphenate(key); { const keyInLowerCase = key.toLowerCase(); if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) { tip(`Prop "${keyInLowerCase}" is passed to component ` + `${formatComponentName( // @ts-expect-error tag is string 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<VNode>. 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 (let i = 0; i < children.length; i++) { if (isArray(children[i])) { return Array.prototype.concat.apply([], children); } } return children; } // 2. When the children contains constructs that always generated nested Arrays, // e.g. <template>, <slot>, v-for, or when the children is provided by user // with hand-written render functions / JSX. In such cases a full normalization // is needed to cater to all possible types of children values. function normalizeChildren(children) { return isPrimitive(children) ? [createTextVNode(children)] : isArray(children) ? normalizeArrayChildren(children) : undefined; } function isTextNode(node) { return isDef(node) && isDef(node.text) && isFalse(node.isComment); } function normalizeArrayChildren(children, nestedIndex) { const res = []; let i, c, lastIndex, last; for (i = 0; i < children.length; i++) { c = children[i]; if (isUndef(c) || typeof c === 'boolean') continue; lastIndex = res.length - 1; last = res[lastIndex]; // nested if (isArray(c)) { if (c.length > 0) { c = normalizeArrayChildren(c, `${nestedIndex || ''}_${i}`); // merge adjacent text nodes if (isTextNode(c[0]) && isTextNode(last)) { res[lastIndex] = createTextVNode(last.text + c[0].text); c.shift(); } res.push.apply(res, c); } } else if (isPrimitive(c)) { if (isTextNode(last)) { // merge adjacent text nodes // this is necessary for SSR hydration because text nodes are // essentially merged when rendered to HTML strings res[lastIndex] = createTextVNode(last.text + c); } else if (c !== '') { // convert primitive to vnode res.push(createTextVNode(c)); } } else { if (isTextNode(c) && isTextNode(last)) { // merge adjacent text nodes res[lastIndex] = createTextVNode(last.text + c.text); } else { // default key for nested array children (likely generated by v-for) if (isTrue(children._isVList) && isDef(c.tag) && isUndef(c.key) && isDef(nestedIndex)) { c.key = `__vlist${nestedIndex}_${i}__`; } res.push(c); } } } return res; } const SIMPLE_NORMALIZE = 1; const ALWAYS_NORMALIZE = 2; // wrapper function for providing a more flexible interface // without getting yelled at by flow function createElement(context, tag, data, children, normalizationType, alwaysNormalize) { if (isArray(data) || isPrimitive(data)) { normalizationType = children; children = data; data = undefined; } if (isTrue(alwaysNormalize)) { normalizationType = ALWAYS_NORMALIZE; } return _createElement(context, tag, data, children, normalizationType); } function _createElement(context, tag, data, children, normalizationType) { if (isDef(data) && isDef(data.__ob__)) { warn$2(`Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` + 'Always create fresh vnode data objects in each render!', context); return createEmptyVNode(); } // object syntax in v-bind if (isDef(data) && isDef(data.is)) { tag = data.is; } if (!tag) { // in case of component :is set to falsy value return createEmptyVNode(); } // warn against non-primitive key if (isDef(data) && isDef(data.key) && !isPrimitive(data.key)) { warn$2('Avoid using non-primitive value as key, ' + 'use string/number value instead.', context); } // support single function children as default scoped slot if (isArray(children) && isFunction(children[0])) { data = data || {}; data.scopedSlots = { default: children[0] }; children.length = 0; } if (normalizationType === ALWAYS_NORMALIZE) { children = normalizeChildren(children); } else if (normalizationType === SIMPLE_NORMALIZE) { children = simpleNormalizeChildren(children); } let vnode, ns; if (typeof tag === 'string') { let Ctor; ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag); if ((!data || !data.pre) && isDef((Ctor = resolveAsset(context.$options, 'components', tag)))) { // component vnode = createComponent(Ctor, data, context, children, tag); } else { // unknown or unlisted namespaced elements // check at runtime because it may get assigned a namespace when its // parent normalizes children vnode = new VNode(tag, data, children, undefined, undefined, context); } } else { // direct component options / constructor vnode = createComponent(tag, data, context, children); } if (isArray(vnode)) { return vnode; } else if (isDef(vnode)) { if (isDef(ns)) applyNS(vnode, ns); if (isDef(data)) registerDeepBindings(data); return vnode; } else { return createEmptyVNode(); } } function applyNS(vnode, ns, force) { vnode.ns = ns; if (vnode.tag === 'foreignObject') { // use default namespace inside foreignObject ns = undefined; force = true; } if (isDef(vnode.children)) { for (let i = 0, l = vnode.children.length; i < l; i++) { const child = vnode.children[i]; if (isDef(child.tag) && (isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) { applyNS(child, ns, force); } } } } // ref #5318 // necessary to ensure parent re-render when deep bindings like :style and // :class are used on slot nodes function registerDeepBindings(data) { if (isObject(data.style)) { traverse(data.style); } if (isObject(data.class)) { traverse(data.class); } } /** * Runtime helper for rendering v-for lists. */ function renderList(val, render) { let ret = null, i, l, keys, key; if (isArray(val) || typeof val === 'string') { ret = new Array(val.length); for (i = 0, l = val.length; i < l; i++) { ret[i] = render(val[i], i); } } else if (typeof val === 'number') { ret = new Array(val); for (i = 0; i < val; i++) { ret[i] = render(i + 1, i); } } else if (isObject(val)) { if (hasSymbol && val[Symbol.iterator]) { ret = []; const iterator = val[Symbol.iterator](); let result = iterator.next(); while (!result.done) { ret.push(render(result.value, ret.length)); result = iterator.next(); } } else { keys = Object.keys(val); ret = new Array(keys.length); for (i = 0, l = keys.length; i < l; i++) { key = keys[i]; ret[i] = render(val[key], key, i); } } } if (!isDef(ret)) { ret = []; } ret._isVList = true; return ret; } /** * Runtime helper for rendering <slot> */ function renderSlot(name, fallbackRender, props, bindObject) { const scopedSlotFn = this.$scopedSlots[name]; let nodes; if (scopedSlotFn) { // scoped slot props = props || {}; if (bindObject) { if (!isObject(bindObject)) { warn$2('slot v-bind without argument expects an Object', this); } props = extend(extend({}, bindObject), props); } nodes = scopedSlotFn(props) || (isFunction(fallbackRender) ? fallbackRender() : fallbackRender); } else { nodes = this.$slots[name] || (isFunction(fallbackRender) ? fallbackRender() : fallbackRender); } const target = props && props.slot; if (target) { return this.$createElement('template', { slot: target }, nodes); } else { return nodes; } } /** * Runtime helper for resolving filters */ function resolveFilter(id) { return resolveAsset(this.$options, 'filters', id, true) || identity; } function isKeyNotMatch(expect, actual) { if (isArray(expect)) { return expect.indexOf(actual) === -1; } else { return expect !== actual; } } /** * Runtime helper for checking keyCodes from config. * exposed as Vue.prototype._k * passing in eventKeyName as last argument separately for backwards compat */ function checkKeyCodes(eventKeyCode, key, builtInKeyCode, eventKeyName, builtInKeyName) { const mappedKeyCode = config.keyCodes[key] || builtInKeyCode; if (builtInKeyName && eventKeyName && !config.keyCodes[key]) { return isKeyNotMatch(builtInKeyName, eventKeyName); } else if (mappedKeyCode) { return isKeyNotMatch(mappedKeyCode, eventKeyCode); } else if (eventKeyName) { return hyphenate(eventKeyName) !== key; } return eventKeyCode === undefined; } /** * Runtime helper for merging v-bind="object" into a VNode's data. */ function bindObjectProps(data, tag, value, asProp, isSync) { if (value) { if (!isObject(value)) { warn$2('v-bind without argument expects an Object or Array value', this); } else { if (isArray(value)) { value = toObject(value); } let hash; for (const key in value) { if (key === 'class' || key === 'style' || isReservedAttribute(key)) { hash = data; } else { const type = data.attrs && data.attrs.type; hash = asProp || config.mustUseProp(tag, type, key) ? data.domProps || (data.domProps = {}) : data.attrs || (data.attrs = {}); } const camelizedKey = camelize(key); const hyphenatedKey = hyphenate(key); if (!(camelizedKey in hash) && !(hyphenatedKey in hash)) { hash[key] = value[key]; if (isSync) { const on = data.on || (data.on = {}); on[`update:${key}`] = function ($event) { value[key] = $event; }; } } } } } return data; } /** * Runtime helper for rendering static trees. */ function renderStatic(index, isInFor) { const cached = this._staticTrees || (this._staticTrees = []); let tree = cached[index]; // if has already-rendered static tree and not inside v-for, // we can reuse the same tree. if (tree && !isInFor) { return tree; } // otherwise, render a fresh tree. tree = cached[index] = this.$options.staticRenderFns[index].call(this._renderProxy, this._c, this // for render fns generated for functional component templates ); markStatic(tree, `__static__${index}`, false); return tree; } /** * Runtime helper for v-once. * Effectively it means marking the node as static with a unique key. */ function markOnce(tree, index, key) { markStatic(tree, `__once__${index}${key ? `_${key}` : ``}`, true); return tree; } function markStatic(tree, key, isOnce) { if (isArray(t