el[key] = '';
el.removeAttribute(key);
return;
} else if (type === 'number') {
// e.g.
el[key] = 0;
el.removeAttribute(key);
return;
}
} // some properties perform value validation and throw
try {
el[key] = value;
} catch (e) {}
} // Async edge case fix requires storing an event listener's attach timestamp.
var _getNow = Date.now;
var skipTimestampCheck = 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 (_getNow() > 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.
_getNow = function _getNow() {
return performance.now();
};
} // #3485: Firefox <= 53 has incorrect Event.timeStamp implementation
// and does not fire microtasks in between event propagation, so safe to exclude.
var ffMatch = navigator.userAgent.match(/firefox\/(\d+)/i);
skipTimestampCheck = !!(ffMatch && Number(ffMatch[1]) <= 53);
} // 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.
var cachedNow = 0;
var p = Promise.resolve();
var reset = function reset() {
cachedNow = 0;
};
var getNow = function getNow() {
return 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) {
if (instance === void 0) {
instance = null;
}
// vei = vue event invokers
var invokers = el._vei || (el._vei = {});
var existingInvoker = invokers[rawName];
if (nextValue && existingInvoker) {
// patch
existingInvoker.value = nextValue;
} else {
var _parseName = parseName(rawName),
name = _parseName[0],
_options2 = _parseName[1];
if (nextValue) {
// add
var invoker = invokers[rawName] = createInvoker(nextValue, instance);
addEventListener(el, name, invoker, _options2);
} else if (existingInvoker) {
// remove
removeEventListener(el, name, existingInvoker, _options2);
invokers[rawName] = undefined;
}
}
}
var optionsModifierRE = /(?:Once|Passive|Capture)$/;
function parseName(name) {
var options;
if (optionsModifierRE.test(name)) {
options = {};
var m;
while (m = name.match(optionsModifierRE)) {
name = name.slice(0, name.length - m[0].length);
options[m[0].toLowerCase()] = true;
}
}
return [hyphenate(name.slice(2)), options];
}
function createInvoker(initialValue, instance) {
var invoker = function 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.
var timeStamp = e.timeStamp || _getNow();
if (skipTimestampCheck || timeStamp >= invoker.attached - 1) {
callWithAsyncErrorHandling(patchStopImmediatePropagation(e, invoker.value), instance, 5
/* NATIVE_EVENT_HANDLER */
, [e]);
}
};
invoker.value = initialValue;
invoker.attached = getNow();
return invoker;
}
function patchStopImmediatePropagation(e, value) {
if (isArray(value)) {
var originalStop = e.stopImmediatePropagation;
e.stopImmediatePropagation = function () {
originalStop.call(e);
e._stopped = true;
};
return value.map(function (fn) {
return function (e) {
return !e._stopped && fn(e);
};
});
} else {
return value;
}
}
var nativeOnRE = /^on[a-z]/;
var forcePatchProp = function forcePatchProp(_, key) {
return key === 'value';
};
var patchProp = function patchProp(el, key, prevValue, nextValue, isSVG, prevChildren, parentComponent, parentSuspense, unmountChildren) {
if (isSVG === void 0) {
isSVG = false;
}
switch (key) {
// special
case 'class':
patchClass(el, nextValue, isSVG);
break;
case 'style':
patchStyle(el, prevValue, nextValue);
break;
default:
if (isOn(key)) {
// ignore v-model listeners
if (!isModelListener(key)) {
patchEvent(el, key, prevValue, nextValue, parentComponent);
}
} else if (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);
}
break;
}
};
function shouldSetAsProp(el, key, value, isSVG) {
if (isSVG) {
// most keys must be set as attribute on svg elements to work
// ...except innerHTML
if (key === 'innerHTML') {
return true;
} // or native onclick with function values
if (key in el && nativeOnRE.test(key) && isFunction(value)) {
return true;
}
return false;
} // spellcheck and draggable are numerated 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') {
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