- value = '';
- needRemove = true;
- } else if (type === 'number') {
- // e.g.
![]()
- // the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
- value = 0;
- needRemove = true;
- }
- }
- // some properties perform value validation and throw,
- // some properties has getter, no setter, will error in 'use strict'
- // eg.
- try {
- el[key] = value;
- } catch (e) {
- _runtimeCore.warn(`Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` + `value ${value} is invalid.`, e);
- }
- needRemove && el.removeAttribute(key);
-}
-// Async edge case fix requires storing an event listener's attach timestamp.
-const [_getNow, skipTimestampCheck] = /*#__PURE__*/ (()=>{
- let _getNow1 = Date.now;
- let skipTimestampCheck1 = false;
- if (typeof window !== 'undefined') {
- // Determine what event timestamp the browser is using. Annoyingly, the
- // timestamp can either be hi-res (relative to page load) or low-res
- // (relative to UNIX epoch), so in order to compare time we have to use the
- // same timestamp type when saving the flush timestamp.
- if (Date.now() > document.createEvent('Event').timeStamp) // if the low-res timestamp which is bigger than the event timestamp
- // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
- // and we need to use the hi-res version for event listeners as well.
- _getNow1 = ()=>performance.now()
- ;
- // #3485: Firefox <= 53 has incorrect Event.timeStamp implementation
- // and does not fire microtasks in between event propagation, so safe to exclude.
- const ffMatch = navigator.userAgent.match(/firefox\/(\d+)/i);
- skipTimestampCheck1 = !!(ffMatch && Number(ffMatch[1]) <= 53);
- }
- return [
- _getNow1,
- skipTimestampCheck1
- ];
-})();
-// To avoid the overhead of repeatedly calling performance.now(), we cache
-// and use the same timestamp for all event listeners attached in the same tick.
-let cachedNow = 0;
-const p = /*#__PURE__*/ Promise.resolve();
-const reset = ()=>{
- cachedNow = 0;
-};
-const getNow = ()=>cachedNow || (p.then(reset), cachedNow = _getNow())
-;
-function addEventListener(el, event, handler, options) {
- el.addEventListener(event, handler, options);
-}
-function removeEventListener(el, event, handler, options) {
- el.removeEventListener(event, handler, options);
-}
-function patchEvent(el, rawName, prevValue, nextValue, instance = null) {
- // vei = vue event invokers
- const invokers = el._vei || (el._vei = {});
- const existingInvoker = invokers[rawName];
- if (nextValue && existingInvoker) // patch
- existingInvoker.value = nextValue;
- else {
- const [name, options] = parseName(rawName);
- if (nextValue) {
- // add
- const invoker = invokers[rawName] = createInvoker(nextValue, instance);
- addEventListener(el, name, invoker, options);
- } else if (existingInvoker) {
- // remove
- removeEventListener(el, name, existingInvoker, options);
- invokers[rawName] = undefined;
- }
- }
-}
-const optionsModifierRE = /(?:Once|Passive|Capture)$/;
-function parseName(name) {
- let options;
- if (optionsModifierRE.test(name)) {
- options = {};
- let m;
- while(m = name.match(optionsModifierRE)){
- name = name.slice(0, name.length - m[0].length);
- options[m[0].toLowerCase()] = true;
- }
- }
- return [
- _shared.hyphenate(name.slice(2)),
- options
- ];
-}
-function createInvoker(initialValue, instance) {
- const invoker = (e)=>{
- // async edge case #6566: inner click event triggers patch, event handler
- // attached to outer element during patch, and triggered again. This
- // happens because browsers fire microtask ticks between event propagation.
- // the solution is simple: we save the timestamp when a handler is attached,
- // and the handler would only fire if the event passed to it was fired
- // AFTER it was attached.
- const timeStamp = e.timeStamp || _getNow();
- if (skipTimestampCheck || timeStamp >= invoker.attached - 1) _runtimeCore.callWithAsyncErrorHandling(patchStopImmediatePropagation(e, invoker.value), instance, 5 /* NATIVE_EVENT_HANDLER */ , [
- e
- ]);
- };
- invoker.value = initialValue;
- invoker.attached = getNow();
- return invoker;
-}
-function patchStopImmediatePropagation(e1, value) {
- if (_shared.isArray(value)) {
- const originalStop = e1.stopImmediatePropagation;
- e1.stopImmediatePropagation = ()=>{
- originalStop.call(e1);
- e1._stopped = true;
- };
- return value.map((fn)=>(e)=>!e._stopped && fn && fn(e)
- );
- } else return value;
-}
-const nativeOnRE = /^on[a-z]/;
-const patchProp = (el, key, prevValue, nextValue, isSVG = false, prevChildren, parentComponent, parentSuspense, unmountChildren)=>{
- if (key === 'class') patchClass(el, nextValue, isSVG);
- else if (key === 'style') patchStyle(el, prevValue, nextValue);
- else if (_shared.isOn(key)) // ignore v-model listeners
- {
- if (!_shared.isModelListener(key)) patchEvent(el, key, prevValue, nextValue, parentComponent);
- } else if (key[0] === '.' ? (key = key.slice(1), true) : key[0] === '^' ? (key = key.slice(1), false) : shouldSetAsProp(el, key, nextValue, isSVG)) patchDOMProp(el, key, nextValue, prevChildren, parentComponent, parentSuspense, unmountChildren);
- else {
- // special case for
with
- // :true-value & :false-value
- // store value as dom properties since non-string values will be
- // stringified.
- if (key === 'true-value') el._trueValue = nextValue;
- else if (key === 'false-value') el._falseValue = nextValue;
- patchAttr(el, key, nextValue, isSVG);
- }
-};
-function shouldSetAsProp(el, key, value, isSVG) {
- if (isSVG) {
- // most keys must be set as attribute on svg elements to work
- // ...except innerHTML & textContent
- if (key === 'innerHTML' || key === 'textContent') return true;
- // or native onclick with function values
- if (key in el && nativeOnRE.test(key) && _shared.isFunction(value)) return true;
- return false;
- }
- // these are enumerated attrs, however their corresponding DOM properties
- // are actually booleans - this leads to setting it with a string "false"
- // value leading it to be coerced to `true`, so we need to always treat
- // them as attributes.
- // Note that `contentEditable` doesn't have this problem: its DOM
- // property is also enumerated string values.
- if (key === 'spellcheck' || key === 'draggable' || key === 'translate') return false;
- // #1787, #2840 form property on form elements is readonly and must be set as
- // attribute.
- if (key === 'form') return false;
- // #1526
must be set as attribute
- if (key === 'list' && el.tagName === 'INPUT') return false;
- // #2766