How to use normalizePropsOptions method in Playwright Internal

Best JavaScript code snippet using playwright-internal

bundle.esm.js

Source:bundle.esm.js Github

copy

Full Screen

...1810 {1811 const options = normalizeEmitsOptions(instance.type.emits);1812 if (options) {1813 if (!(event in options)) {1814 const propsOptions = normalizePropsOptions(instance.type.props)[0];1815 if (!propsOptions || !(`on` + capitalize(event) in propsOptions)) {1816 warn(`Component emitted event "${event}" but it is neither declared in ` +1817 `the emits option nor as an "on${capitalize(event)}" prop.`);1818 }1819 }1820 else {1821 const validator = options[event];1822 if (isFunction(validator)) {1823 const isValid = validator(...args);1824 if (!isValid) {1825 warn(`Invalid event arguments: event validation failed for event "${event}".`);1826 }1827 }1828 }1829 }1830 }1831 let handler = props[`on${capitalize(event)}`];1832 // for v-model update:xxx events, also trigger kebab-case equivalent1833 // for props passed via kebab-case1834 if (!handler && event.startsWith('update:')) {1835 event = hyphenate(event);1836 handler = props[`on${capitalize(event)}`];1837 }1838 if (handler) {1839 callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args);1840 }1841}1842function normalizeEmitsOptions(options) {1843 if (!options) {1844 return;1845 }1846 else if (isArray(options)) {1847 if (options._n) {1848 return options._n;1849 }1850 const normalized = {};1851 options.forEach(key => (normalized[key] = null));1852 def(options, '_n', normalized);1853 return normalized;1854 }1855 else {1856 return options;1857 }1858}1859// Check if an incoming prop key is a declared emit event listener.1860// e.g. With `emits: { click: null }`, props named `onClick` and `onclick` are1861// both considered matched listeners.1862function isEmitListener(emits, key) {1863 return (isOn(key) &&1864 (hasOwn((emits = normalizeEmitsOptions(emits)), key[2].toLowerCase() + key.slice(3)) ||1865 hasOwn(emits, key.slice(2))));1866}1867function initProps(instance, rawProps, isStateful, // result of bitwise flag comparison1868isSSR = false) {1869 const props = {};1870 const attrs = {};1871 def(attrs, InternalObjectKey, 1);1872 setFullProps(instance, rawProps, props, attrs);1873 const options = instance.type.props;1874 // validation1875 if ( options && rawProps) {1876 validateProps(props, options);1877 }1878 if (isStateful) {1879 // stateful1880 instance.props = isSSR ? props : shallowReactive(props);1881 }1882 else {1883 if (!options) {1884 // functional w/ optional props, props === attrs1885 instance.props = attrs;1886 }1887 else {1888 // functional w/ declared props1889 instance.props = props;1890 }1891 }1892 instance.attrs = attrs;1893}1894function updateProps(instance, rawProps, rawPrevProps, optimized) {1895 const { props, attrs, vnode: { patchFlag } } = instance;1896 const rawOptions = instance.type.props;1897 const rawCurrentProps = toRaw(props);1898 const { 0: options } = normalizePropsOptions(rawOptions);1899 if ((optimized || patchFlag > 0) && !(patchFlag & 16 /* FULL_PROPS */)) {1900 if (patchFlag & 8 /* PROPS */) {1901 // Compiler-generated props & no keys change, just set the updated1902 // the props.1903 const propsToUpdate = instance.vnode.dynamicProps;1904 for (let i = 0; i < propsToUpdate.length; i++) {1905 const key = propsToUpdate[i];1906 // PROPS flag guarantees rawProps to be non-null1907 const value = rawProps[key];1908 if (options) {1909 // attr / props separation was done on init and will be consistent1910 // in this code path, so just check if attrs have it.1911 if (hasOwn(attrs, key)) {1912 attrs[key] = value;1913 }1914 else {1915 const camelizedKey = camelize(key);1916 props[camelizedKey] = resolvePropValue(options, rawCurrentProps, camelizedKey, value);1917 }1918 }1919 else {1920 attrs[key] = value;1921 }1922 }1923 }1924 }1925 else {1926 // full props update.1927 setFullProps(instance, rawProps, props, attrs);1928 // in case of dynamic props, check if we need to delete keys from1929 // the props object1930 let kebabKey;1931 for (const key in rawCurrentProps) {1932 if (!rawProps ||1933 (!hasOwn(rawProps, key) &&1934 // it's possible the original props was passed in as kebab-case1935 // and converted to camelCase (#955)1936 ((kebabKey = hyphenate(key)) === key || !hasOwn(rawProps, kebabKey)))) {1937 if (options) {1938 if (rawPrevProps && rawPrevProps[kebabKey] !== undefined) {1939 props[key] = resolvePropValue(options, rawProps || EMPTY_OBJ, key, undefined);1940 }1941 }1942 else {1943 delete props[key];1944 }1945 }1946 }1947 // in the case of functional component w/o props declaration, props and1948 // attrs point to the same object so it should already have been updated.1949 if (attrs !== rawCurrentProps) {1950 for (const key in attrs) {1951 if (!rawProps || !hasOwn(rawProps, key)) {1952 delete attrs[key];1953 }1954 }1955 }1956 }1957 if ( rawOptions && rawProps) {1958 validateProps(props, rawOptions);1959 }1960}1961function setFullProps(instance, rawProps, props, attrs) {1962 const { 0: options, 1: needCastKeys } = normalizePropsOptions(instance.type.props);1963 const emits = instance.type.emits;1964 if (rawProps) {1965 for (const key in rawProps) {1966 const value = rawProps[key];1967 // key, ref are reserved and never passed down1968 if (isReservedProp(key)) {1969 continue;1970 }1971 // prop option names are camelized during normalization, so to support1972 // kebab -> camel conversion here we need to camelize the key.1973 let camelKey;1974 if (options && hasOwn(options, (camelKey = camelize(key)))) {1975 props[camelKey] = value;1976 }1977 else if (!emits || !isEmitListener(emits, key)) {1978 // Any non-declared (either as a prop or an emitted event) props are put1979 // into a separate `attrs` object for spreading. Make sure to preserve1980 // original key casing1981 attrs[key] = value;1982 }1983 }1984 }1985 if (needCastKeys) {1986 const rawCurrentProps = toRaw(props);1987 for (let i = 0; i < needCastKeys.length; i++) {1988 const key = needCastKeys[i];1989 props[key] = resolvePropValue(options, rawCurrentProps, key, rawCurrentProps[key]);1990 }1991 }1992}1993function resolvePropValue(options, props, key, value) {1994 const opt = options[key];1995 if (opt != null) {1996 const hasDefault = hasOwn(opt, 'default');1997 // default values1998 if (hasDefault && value === undefined) {1999 const defaultValue = opt.default;2000 value = isFunction(defaultValue) ? defaultValue() : defaultValue;2001 }2002 // boolean casting2003 if (opt[0 /* shouldCast */]) {2004 if (!hasOwn(props, key) && !hasDefault) {2005 value = false;2006 }2007 else if (opt[1 /* shouldCastTrue */] &&2008 (value === '' || value === hyphenate(key))) {2009 value = true;2010 }2011 }2012 }2013 return value;2014}2015function normalizePropsOptions(raw) {2016 if (!raw) {2017 return EMPTY_ARR;2018 }2019 if (raw._n) {2020 return raw._n;2021 }2022 const normalized = {};2023 const needCastKeys = [];2024 if (isArray(raw)) {2025 for (let i = 0; i < raw.length; i++) {2026 if ( !isString(raw[i])) {2027 warn(`props must be strings when using array syntax.`, raw[i]);2028 }2029 const normalizedKey = camelize(raw[i]);2030 if (validatePropName(normalizedKey)) {2031 normalized[normalizedKey] = EMPTY_OBJ;2032 }2033 }2034 }2035 else {2036 if ( !isObject(raw)) {2037 warn(`invalid props options`, raw);2038 }2039 for (const key in raw) {2040 const normalizedKey = camelize(key);2041 if (validatePropName(normalizedKey)) {2042 const opt = raw[key];2043 const prop = (normalized[normalizedKey] =2044 isArray(opt) || isFunction(opt) ? { type: opt } : opt);2045 if (prop) {2046 const booleanIndex = getTypeIndex(Boolean, prop.type);2047 const stringIndex = getTypeIndex(String, prop.type);2048 prop[0 /* shouldCast */] = booleanIndex > -1;2049 prop[1 /* shouldCastTrue */] =2050 stringIndex < 0 || booleanIndex < stringIndex;2051 // if the prop needs boolean casting or default value2052 if (booleanIndex > -1 || hasOwn(prop, 'default')) {2053 needCastKeys.push(normalizedKey);2054 }2055 }2056 }2057 }2058 }2059 const normalizedEntry = [normalized, needCastKeys];2060 def(raw, '_n', normalizedEntry);2061 return normalizedEntry;2062}2063// use function string name to check type constructors2064// so that it works across vms / iframes.2065function getType(ctor) {2066 const match = ctor && ctor.toString().match(/^\s*function (\w+)/);2067 return match ? match[1] : '';2068}2069function isSameType(a, b) {2070 return getType(a) === getType(b);2071}2072function getTypeIndex(type, expectedTypes) {2073 if (isArray(expectedTypes)) {2074 for (let i = 0, len = expectedTypes.length; i < len; i++) {2075 if (isSameType(expectedTypes[i], type)) {2076 return i;2077 }2078 }2079 }2080 else if (isFunction(expectedTypes)) {2081 return isSameType(expectedTypes, type) ? 0 : -1;2082 }2083 return -1;2084}2085function validateProps(props, rawOptions) {2086 const rawValues = toRaw(props);2087 const options = normalizePropsOptions(rawOptions)[0];2088 for (const key in options) {2089 let opt = options[key];2090 if (opt == null)2091 continue;2092 validateProp(key, rawValues[key], opt, !hasOwn(rawValues, key));2093 }2094}2095function validatePropName(key) {2096 if (key[0] !== '$') {2097 return true;2098 }2099 else {2100 warn(`Invalid prop name: "${key}" is a reserved property.`);2101 }2102 return false;2103}2104function validateProp(name, value, prop, isAbsent) {2105 const { type, required, validator } = prop;2106 // required!2107 if (required && isAbsent) {2108 warn('Missing required prop: "' + name + '"');2109 return;2110 }2111 // missing but optional2112 if (value == null && !prop.required) {2113 return;2114 }2115 // type check2116 if (type != null && type !== true) {2117 let isValid = false;2118 const types = isArray(type) ? type : [type];2119 const expectedTypes = [];2120 // value is valid as long as one of the specified types match2121 for (let i = 0; i < types.length && !isValid; i++) {2122 const { valid, expectedType } = assertType(value, types[i]);2123 expectedTypes.push(expectedType || '');2124 isValid = valid;2125 }2126 if (!isValid) {2127 warn(getInvalidTypeMessage(name, value, expectedTypes));2128 return;2129 }2130 }2131 // custom validator2132 if (validator && !validator(value)) {2133 warn('Invalid prop: custom validator check failed for prop "' + name + '".');2134 }2135}2136const isSimpleType = /*#__PURE__*/ makeMap('String,Number,Boolean,Function,Symbol');2137function assertType(value, type) {2138 let valid;2139 const expectedType = getType(type);2140 if (isSimpleType(expectedType)) {2141 const t = typeof value;2142 valid = t === expectedType.toLowerCase();2143 // for primitive wrapper objects2144 if (!valid && t === 'object') {2145 valid = value instanceof type;2146 }2147 }2148 else if (expectedType === 'Object') {2149 valid = toRawType(value) === 'Object';2150 }2151 else if (expectedType === 'Array') {2152 valid = isArray(value);2153 }2154 else {2155 valid = value instanceof type;2156 }2157 return {2158 valid,2159 expectedType2160 };2161}2162function getInvalidTypeMessage(name, value, expectedTypes) {2163 let message = `Invalid prop: type check failed for prop "${name}".` +2164 ` Expected ${expectedTypes.map(capitalize).join(', ')}`;2165 const expectedType = expectedTypes[0];2166 const receivedType = toRawType(value);2167 const expectedValue = styleValue(value, expectedType);2168 const receivedValue = styleValue(value, receivedType);2169 // check if we need to specify expected value2170 if (expectedTypes.length === 1 &&2171 isExplicable(expectedType) &&2172 !isBoolean(expectedType, receivedType)) {2173 message += ` with value ${expectedValue}`;2174 }2175 message += `, got ${receivedType} `;2176 // check if we need to specify received value2177 if (isExplicable(receivedType)) {2178 message += `with value ${receivedValue}.`;2179 }2180 return message;2181}2182function styleValue(value, type) {2183 if (type === 'String') {2184 return `"${value}"`;2185 }2186 else if (type === 'Number') {2187 return `${Number(value)}`;2188 }2189 else {2190 return `${value}`;2191 }2192}2193function isExplicable(type) {2194 const explicitTypes = ['string', 'number', 'boolean'];2195 return explicitTypes.some(elem => type.toLowerCase() === elem);2196}2197function isBoolean(...args) {2198 return args.some(elem => elem.toLowerCase() === 'boolean');2199}2200const isInternalKey = (key) => key[0] === '_' || key === '$stable';2201const normalizeSlotValue = (value) => isArray(value)2202 ? value.map(normalizeVNode)2203 : [normalizeVNode(value)];2204const normalizeSlot = (key, rawSlot, ctx) => withCtx((props) => {2205 if ( currentInstance) {2206 warn(`Slot "${key}" invoked outside of the render function: ` +2207 `this will not track dependencies used in the slot. ` +2208 `Invoke the slot function inside the render function instead.`);2209 }2210 return normalizeSlotValue(rawSlot(props));2211}, ctx);2212const normalizeObjectSlots = (rawSlots, slots) => {2213 const ctx = rawSlots._ctx;2214 for (const key in rawSlots) {2215 if (isInternalKey(key))2216 continue;2217 const value = rawSlots[key];2218 if (isFunction(value)) {2219 slots[key] = normalizeSlot(key, value, ctx);2220 }2221 else if (value != null) {2222 {2223 warn(`Non-function value encountered for slot "${key}". ` +2224 `Prefer function slots for better performance.`);2225 }2226 const normalized = normalizeSlotValue(value);2227 slots[key] = () => normalized;2228 }2229 }2230};2231const normalizeVNodeSlots = (instance, children) => {2232 if ( !isKeepAlive(instance.vnode)) {2233 warn(`Non-function value encountered for default slot. ` +2234 `Prefer function slots for better performance.`);2235 }2236 const normalized = normalizeSlotValue(children);2237 instance.slots.default = () => normalized;2238};2239const initSlots = (instance, children) => {2240 if (instance.vnode.shapeFlag & 32 /* SLOTS_CHILDREN */) {2241 if (children._ === 1) {2242 instance.slots = children;2243 }2244 else {2245 normalizeObjectSlots(children, (instance.slots = {}));2246 }2247 }2248 else {2249 instance.slots = {};2250 if (children) {2251 normalizeVNodeSlots(instance, children);2252 }2253 }2254 def(instance.slots, InternalObjectKey, 1);2255};2256const updateSlots = (instance, children) => {2257 const { vnode, slots } = instance;2258 let needDeletionCheck = true;2259 let deletionComparisonTarget = EMPTY_OBJ;2260 if (vnode.shapeFlag & 32 /* SLOTS_CHILDREN */) {2261 if (children._ === 1) {2262 // compiled slots.2263 if (2264 // bail on dynamic slots (v-if, v-for, reference of scope variables)2265 !(vnode.patchFlag & 1024 /* DYNAMIC_SLOTS */) &&2266 // bail on HRM updates2267 !( instance.parent && instance.parent.renderUpdated)) {2268 // compiled AND static.2269 // no need to update, and skip stale slots removal.2270 needDeletionCheck = false;2271 }2272 else {2273 // compiled but dynamic - update slots, but skip normalization.2274 extend(slots, children);2275 }2276 }2277 else {2278 needDeletionCheck = !children.$stable;2279 normalizeObjectSlots(children, slots);2280 }2281 deletionComparisonTarget = children;2282 }2283 else if (children) {2284 // non slot object children (direct value) passed to a component2285 normalizeVNodeSlots(instance, children);2286 deletionComparisonTarget = { default: 1 };2287 }2288 // delete stale slots2289 if (needDeletionCheck) {2290 for (const key in slots) {2291 if (!isInternalKey(key) && !(key in deletionComparisonTarget)) {2292 delete slots[key];2293 }2294 }2295 }2296};2297/**2298Runtime helper for applying directives to a vnode. Example usage:2299const comp = resolveComponent('comp')2300const foo = resolveDirective('foo')2301const bar = resolveDirective('bar')2302return withDirectives(h(comp), [2303 [foo, this.x],2304 [bar, this.y]2305])2306*/2307const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text');2308function validateDirectiveName(name) {2309 if (isBuiltInDirective(name)) {2310 warn('Do not use built-in directive ids as custom directive id: ' + name);2311 }2312}2313function invokeDirectiveHook(vnode, prevVNode, instance, name) {2314 const bindings = vnode.dirs;2315 const oldBindings = prevVNode && prevVNode.dirs;2316 for (let i = 0; i < bindings.length; i++) {2317 const binding = bindings[i];2318 if (oldBindings) {2319 binding.oldValue = oldBindings[i].value;2320 }2321 const hook = binding.dir[name];2322 if (hook) {2323 callWithAsyncErrorHandling(hook, instance, 8 /* DIRECTIVE_HOOK */, [2324 vnode.el,2325 binding,2326 vnode,2327 prevVNode2328 ]);2329 }2330 }2331}2332function createAppContext() {2333 return {2334 config: {2335 isNativeTag: NO,2336 devtools: true,2337 performance: false,2338 globalProperties: {},2339 optionMergeStrategies: {},2340 isCustomElement: NO,2341 errorHandler: undefined,2342 warnHandler: undefined2343 },2344 mixins: [],2345 components: {},2346 directives: {},2347 provides: Object.create(null)2348 };2349}2350function createAppAPI(render, hydrate) {2351 return function createApp(rootComponent, rootProps = null) {2352 if (rootProps != null && !isObject(rootProps)) {2353 warn(`root props passed to app.mount() must be an object.`);2354 rootProps = null;2355 }2356 const context = createAppContext();2357 const installedPlugins = new Set();2358 let isMounted = false;2359 const app = {2360 _component: rootComponent,2361 _props: rootProps,2362 _container: null,2363 _context: context,2364 get config() {2365 return context.config;2366 },2367 set config(v) {2368 {2369 warn(`app.config cannot be replaced. Modify individual options instead.`);2370 }2371 },2372 use(plugin, ...options) {2373 if (installedPlugins.has(plugin)) {2374 warn(`Plugin has already been applied to target app.`);2375 }2376 else if (plugin && isFunction(plugin.install)) {2377 installedPlugins.add(plugin);2378 plugin.install(app, ...options);2379 }2380 else if (isFunction(plugin)) {2381 installedPlugins.add(plugin);2382 plugin(app, ...options);2383 }2384 else {2385 warn(`A plugin must either be a function or an object with an "install" ` +2386 `function.`);2387 }2388 return app;2389 },2390 mixin(mixin) {2391 {2392 if (!context.mixins.includes(mixin)) {2393 context.mixins.push(mixin);2394 }2395 else {2396 warn('Mixin has already been applied to target app' +2397 (mixin.name ? `: ${mixin.name}` : ''));2398 }2399 }2400 return app;2401 },2402 component(name, component) {2403 {2404 validateComponentName(name, context.config);2405 }2406 if (!component) {2407 return context.components[name];2408 }2409 if ( context.components[name]) {2410 warn(`Component "${name}" has already been registered in target app.`);2411 }2412 context.components[name] = component;2413 return app;2414 },2415 directive(name, directive) {2416 {2417 validateDirectiveName(name);2418 }2419 if (!directive) {2420 return context.directives[name];2421 }2422 if ( context.directives[name]) {2423 warn(`Directive "${name}" has already been registered in target app.`);2424 }2425 context.directives[name] = directive;2426 return app;2427 },2428 mount(rootContainer, isHydrate) {2429 if (!isMounted) {2430 const vnode = createVNode(rootComponent, rootProps);2431 // store app context on the root VNode.2432 // this will be set on the root instance on initial mount.2433 vnode.appContext = context;2434 // HMR root reload2435 {2436 context.reload = () => {2437 render(cloneVNode(vnode), rootContainer);2438 };2439 }2440 if (isHydrate && hydrate) {2441 hydrate(vnode, rootContainer);2442 }2443 else {2444 render(vnode, rootContainer);2445 }2446 isMounted = true;2447 app._container = rootContainer;2448 return vnode.component.proxy;2449 }2450 else {2451 warn(`App has already been mounted. Create a new app instance instead.`);2452 }2453 },2454 unmount() {2455 if (isMounted) {2456 render(null, app._container);2457 }2458 else {2459 warn(`Cannot unmount an app that is not mounted.`);2460 }2461 },2462 provide(key, value) {2463 if ( key in context.provides) {2464 warn(`App already provides property with key "${String(key)}". ` +2465 `It will be overwritten with the new value.`);2466 }2467 // TypeScript doesn't allow symbols as index type2468 // https://github.com/Microsoft/TypeScript/issues/245872469 context.provides[key] = value;2470 return app;2471 }2472 };2473 return app;2474 };2475}2476// Expose the HMR runtime on the global object2477// This makes it entirely tree-shakable without polluting the exports and makes2478// it easier to be used in toolings like vue-loader2479// Note: for a component to be eligible for HMR it also needs the __hmrId option2480// to be set so that its instances can be registered / removed.2481{2482 const globalObject = typeof global !== 'undefined'2483 ? global2484 : typeof self !== 'undefined'2485 ? self2486 : typeof window !== 'undefined'2487 ? window2488 : {};2489 globalObject.__VUE_HMR_RUNTIME__ = {2490 createRecord: tryWrap(createRecord),2491 rerender: tryWrap(rerender),2492 reload: tryWrap(reload)2493 };2494}2495const map = new Map();2496function registerHMR(instance) {2497 const id = instance.type.__hmrId;2498 let record = map.get(id);2499 if (!record) {2500 createRecord(id, instance.type);2501 record = map.get(id);2502 }2503 record.add(instance);2504}2505function unregisterHMR(instance) {2506 map.get(instance.type.__hmrId).delete(instance);2507}2508function createRecord(id, comp) {2509 if (map.has(id)) {2510 return false;2511 }2512 map.set(id, new Set());2513 return true;2514}2515function rerender(id, newRender) {2516 const record = map.get(id);2517 if (!record)2518 return;2519 // Array.from creates a snapshot which avoids the set being mutated during2520 // updates2521 Array.from(record).forEach(instance => {2522 if (newRender) {2523 instance.render = newRender;2524 }2525 instance.renderCache = [];2526 // this flag forces child components with slot content to update2527 instance.renderUpdated = true;2528 instance.update();2529 instance.renderUpdated = false;2530 });2531}2532function reload(id, newComp) {2533 const record = map.get(id);2534 if (!record)2535 return;2536 // Array.from creates a snapshot which avoids the set being mutated during2537 // updates2538 Array.from(record).forEach(instance => {2539 const comp = instance.type;2540 if (!comp.__hmrUpdated) {2541 // 1. Update existing comp definition to match new one2542 Object.assign(comp, newComp);2543 for (const key in comp) {2544 if (!(key in newComp)) {2545 delete comp[key];2546 }2547 }2548 // 2. Mark component dirty. This forces the renderer to replace the component2549 // on patch.2550 comp.__hmrUpdated = true;2551 // 3. Make sure to unmark the component after the reload.2552 queuePostFlushCb(() => {2553 comp.__hmrUpdated = false;2554 });2555 }2556 if (instance.parent) {2557 // 4. Force the parent instance to re-render. This will cause all updated2558 // components to be unmounted and re-mounted. Queue the update so that we2559 // don't end up forcing the same parent to re-render multiple times.2560 queueJob(instance.parent.update);2561 }2562 else if (instance.appContext.reload) {2563 // root instance mounted via createApp() has a reload method2564 instance.appContext.reload();2565 }2566 else if (typeof window !== 'undefined') {2567 // root instance inside tree created via raw render(). Force reload.2568 window.location.reload();2569 }2570 else {2571 console.warn('[HMR] Root or manually mounted instance modified. Full reload required.');2572 }2573 });2574}2575function tryWrap(fn) {2576 return (id, arg) => {2577 try {2578 return fn(id, arg);2579 }2580 catch (e) {2581 console.error(e);2582 console.warn(`[HMR] Something went wrong during Vue component hot-reload. ` +2583 `Full reload required.`);2584 }2585 };2586}2587let supported;2588let perf;2589function startMeasure(instance, type) {2590 if (instance.appContext.config.performance && isSupported()) {2591 perf.mark(`vue-${type}-${instance.uid}`);2592 }2593}2594function endMeasure(instance, type) {2595 if (instance.appContext.config.performance && isSupported()) {2596 const startTag = `vue-${type}-${instance.uid}`;2597 const endTag = startTag + `:end`;2598 perf.mark(endTag);2599 perf.measure(`<${formatComponentName(instance.type)}> ${type}`, startTag, endTag);2600 perf.clearMarks(startTag);2601 perf.clearMarks(endTag);2602 }2603}2604function isSupported() {2605 if (supported !== undefined) {2606 return supported;2607 }2608 if (typeof window !== 'undefined' && window.performance) {2609 supported = true;2610 perf = window.performance;2611 }2612 else {2613 supported = false;2614 }2615 return supported;2616}2617function createDevEffectOptions(instance) {2618 return {2619 scheduler: queueJob,2620 onTrack: instance.rtc ? e => invokeArrayFns(instance.rtc, e) : void 0,2621 onTrigger: instance.rtg ? e => invokeArrayFns(instance.rtg, e) : void 02622 };2623}2624const queuePostRenderEffect = queueEffectWithSuspense2625 ;2626/**2627 * The createRenderer function accepts two generic arguments:2628 * HostNode and HostElement, corresponding to Node and Element types in the2629 * host environment. For example, for runtime-dom, HostNode would be the DOM2630 * `Node` interface and HostElement would be the DOM `Element` interface.2631 *2632 * Custom renderers can pass in the platform specific types like this:2633 *2634 * ``` js2635 * const { render, createApp } = createRenderer<Node, Element>({2636 * patchProp,2637 * ...nodeOps2638 * })2639 * ```2640 */2641function createRenderer(options) {2642 return baseCreateRenderer(options);2643}2644// implementation2645function baseCreateRenderer(options, createHydrationFns) {2646 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, setScopeId: hostSetScopeId = NOOP, cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent, setStaticContent: hostSetStaticContent } = options;2647 // Note: functions inside this closure should use `const xxx = () => {}`2648 // style in order to prevent being inlined by minifiers.2649 const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) => {2650 // patching & not same type, unmount old tree2651 if (n1 && !isSameVNodeType(n1, n2)) {2652 anchor = getNextHostNode(n1);2653 unmount(n1, parentComponent, parentSuspense, true);2654 n1 = null;2655 }2656 if (n2.patchFlag === -2 /* BAIL */) {2657 optimized = false;2658 n2.dynamicChildren = null;2659 }2660 const { type, ref, shapeFlag } = n2;2661 switch (type) {2662 case Text:2663 processText(n1, n2, container, anchor);2664 break;2665 case Comment:2666 processCommentNode(n1, n2, container, anchor);2667 break;2668 case Static:2669 if (n1 == null) {2670 mountStaticNode(n2, container, anchor, isSVG);2671 }2672 else {2673 // static nodes are only patched during dev for HMR2674 n2.el = n1.el;2675 if (n2.children !== n1.children) {2676 hostSetStaticContent(n2.el, n2.children);2677 }2678 }2679 break;2680 case Fragment:2681 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2682 break;2683 default:2684 if (shapeFlag & 1 /* ELEMENT */) {2685 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2686 }2687 else if (shapeFlag & 6 /* COMPONENT */) {2688 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2689 }2690 else if (shapeFlag & 64 /* TELEPORT */) {2691 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);2692 }2693 else if ( shapeFlag & 128 /* SUSPENSE */) {2694 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);2695 }2696 else {2697 warn('Invalid VNode type:', type, `(${typeof type})`);2698 }2699 }2700 // set ref2701 if (ref != null && parentComponent) {2702 const refValue = shapeFlag & 4 /* STATEFUL_COMPONENT */ ? n2.component.proxy : n2.el;2703 setRef(ref, n1 && n1.ref, parentComponent, refValue);2704 }2705 };2706 const processText = (n1, n2, container, anchor) => {2707 if (n1 == null) {2708 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);2709 }2710 else {2711 const el = (n2.el = n1.el);2712 if (n2.children !== n1.children) {2713 hostSetText(el, n2.children);2714 }2715 }2716 };2717 const processCommentNode = (n1, n2, container, anchor) => {2718 if (n1 == null) {2719 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);2720 }2721 else {2722 // there's no support for dynamic comments2723 n2.el = n1.el;2724 }2725 };2726 const mountStaticNode = (n2, container, anchor, isSVG) => {2727 if (n2.el && hostCloneNode !== undefined) {2728 hostInsert(hostCloneNode(n2.el), container, anchor);2729 }2730 else {2731 // static nodes are only present when used with compiler-dom/runtime-dom2732 // which guarantees presence of hostInsertStaticContent.2733 n2.el = hostInsertStaticContent(n2.children, container, anchor, isSVG);2734 }2735 };2736 const processElement = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {2737 isSVG = isSVG || n2.type === 'svg';2738 if (n1 == null) {2739 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2740 }2741 else {2742 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);2743 }2744 };2745 const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {2746 let el;2747 let vnodeHook;2748 const { type, props, shapeFlag, transition, scopeId, patchFlag, dirs } = vnode;2749 if (vnode.el &&2750 hostCloneNode !== undefined &&2751 patchFlag === -1 /* HOISTED */) {2752 // If a vnode has non-null el, it means it's being reused.2753 // Only static vnodes can be reused, so its mounted DOM nodes should be2754 // exactly the same, and we can simply do a clone here.2755 el = vnode.el = hostCloneNode(vnode.el);2756 }2757 else {2758 el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is);2759 // props2760 if (props) {2761 for (const key in props) {2762 if (!isReservedProp(key)) {2763 hostPatchProp(el, key, null, props[key], isSVG);2764 }2765 }2766 if ((vnodeHook = props.onVnodeBeforeMount)) {2767 invokeVNodeHook(vnodeHook, parentComponent, vnode);2768 }2769 }2770 if (dirs) {2771 invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount');2772 }2773 // scopeId2774 if (scopeId) {2775 hostSetScopeId(el, scopeId);2776 }2777 const treeOwnerId = parentComponent && parentComponent.type.__scopeId;2778 // vnode's own scopeId and the current patched component's scopeId is2779 // different - this is a slot content node.2780 if (treeOwnerId && treeOwnerId !== scopeId) {2781 hostSetScopeId(el, treeOwnerId + '-s');2782 }2783 // children2784 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2785 hostSetElementText(el, vnode.children);2786 }2787 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2788 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', optimized || !!vnode.dynamicChildren);2789 }2790 if (transition && !transition.persisted) {2791 transition.beforeEnter(el);2792 }2793 }2794 hostInsert(el, container, anchor);2795 if ((vnodeHook = props && props.onVnodeMounted) ||2796 (transition && !transition.persisted) ||2797 dirs) {2798 queuePostRenderEffect(() => {2799 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);2800 transition && !transition.persisted && transition.enter(el);2801 dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted');2802 }, parentSuspense);2803 }2804 };2805 const mountChildren = (children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) => {2806 for (let i = start; i < children.length; i++) {2807 const child = (children[i] = optimized2808 ? cloneIfMounted(children[i])2809 : normalizeVNode(children[i]));2810 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2811 }2812 };2813 const patchElement = (n1, n2, parentComponent, parentSuspense, isSVG, optimized) => {2814 const el = (n2.el = n1.el);2815 let { patchFlag, dynamicChildren, dirs } = n2;2816 const oldProps = (n1 && n1.props) || EMPTY_OBJ;2817 const newProps = n2.props || EMPTY_OBJ;2818 let vnodeHook;2819 if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {2820 invokeVNodeHook(vnodeHook, parentComponent, n2, n1);2821 }2822 if (dirs) {2823 invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate');2824 }2825 if ( parentComponent && parentComponent.renderUpdated) {2826 // HMR updated, force full diff2827 patchFlag = 0;2828 optimized = false;2829 dynamicChildren = null;2830 }2831 if (patchFlag > 0) {2832 // the presence of a patchFlag means this element's render code was2833 // generated by the compiler and can take the fast path.2834 // in this path old node and new node are guaranteed to have the same shape2835 // (i.e. at the exact same position in the source template)2836 if (patchFlag & 16 /* FULL_PROPS */) {2837 // element props contain dynamic keys, full diff needed2838 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2839 }2840 else {2841 // class2842 // this flag is matched when the element has dynamic class bindings.2843 if (patchFlag & 2 /* CLASS */) {2844 if (oldProps.class !== newProps.class) {2845 hostPatchProp(el, 'class', null, newProps.class, isSVG);2846 }2847 }2848 // style2849 // this flag is matched when the element has dynamic style bindings2850 if (patchFlag & 4 /* STYLE */) {2851 hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG);2852 }2853 // props2854 // This flag is matched when the element has dynamic prop/attr bindings2855 // other than class and style. The keys of dynamic prop/attrs are saved for2856 // faster iteration.2857 // Note dynamic keys like :[foo]="bar" will cause this optimization to2858 // bail out and go through a full diff because we need to unset the old key2859 if (patchFlag & 8 /* PROPS */) {2860 // if the flag is present then dynamicProps must be non-null2861 const propsToUpdate = n2.dynamicProps;2862 for (let i = 0; i < propsToUpdate.length; i++) {2863 const key = propsToUpdate[i];2864 const prev = oldProps[key];2865 const next = newProps[key];2866 if (prev !== next) {2867 hostPatchProp(el, key, prev, next, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);2868 }2869 }2870 }2871 }2872 // text2873 // This flag is matched when the element has only dynamic text children.2874 if (patchFlag & 1 /* TEXT */) {2875 if (n1.children !== n2.children) {2876 hostSetElementText(el, n2.children);2877 }2878 }2879 }2880 else if (!optimized && dynamicChildren == null) {2881 // unoptimized, full diff2882 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2883 }2884 const areChildrenSVG = isSVG && n2.type !== 'foreignObject';2885 if (dynamicChildren) {2886 patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, areChildrenSVG);2887 }2888 else if (!optimized) {2889 // full diff2890 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, areChildrenSVG);2891 }2892 if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {2893 queuePostRenderEffect(() => {2894 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1);2895 dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated');2896 }, parentSuspense);2897 }2898 };2899 // The fast path for blocks.2900 const patchBlockChildren = (oldChildren, newChildren, fallbackContainer, parentComponent, parentSuspense, isSVG) => {2901 for (let i = 0; i < newChildren.length; i++) {2902 const oldVNode = oldChildren[i];2903 const newVNode = newChildren[i];2904 // Determine the container (parent element) for the patch.2905 const container = 2906 // - In the case of a Fragment, we need to provide the actual parent2907 // of the Fragment itself so it can move its children.2908 oldVNode.type === Fragment ||2909 // - In the case of different nodes, there is going to be a replacement2910 // which also requires the correct parent container2911 !isSameVNodeType(oldVNode, newVNode) ||2912 // - In the case of a component, it could contain anything.2913 oldVNode.shapeFlag & 6 /* COMPONENT */2914 ? hostParentNode(oldVNode.el)2915 : // In other cases, the parent container is not actually used so we2916 // just pass the block element here to avoid a DOM parentNode call.2917 fallbackContainer;2918 patch(oldVNode, newVNode, container, null, parentComponent, parentSuspense, isSVG, true);2919 }2920 };2921 const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {2922 if (oldProps !== newProps) {2923 for (const key in newProps) {2924 if (isReservedProp(key))2925 continue;2926 const next = newProps[key];2927 const prev = oldProps[key];2928 if (next !== prev) {2929 hostPatchProp(el, key, prev, next, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2930 }2931 }2932 if (oldProps !== EMPTY_OBJ) {2933 for (const key in oldProps) {2934 if (!isReservedProp(key) && !(key in newProps)) {2935 hostPatchProp(el, key, oldProps[key], null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2936 }2937 }2938 }2939 }2940 };2941 const processFragment = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {2942 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''));2943 const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''));2944 let { patchFlag, dynamicChildren } = n2;2945 if (patchFlag > 0) {2946 optimized = true;2947 }2948 if ( parentComponent && parentComponent.renderUpdated) {2949 // HMR updated, force full diff2950 patchFlag = 0;2951 optimized = false;2952 dynamicChildren = null;2953 }2954 if (n1 == null) {2955 hostInsert(fragmentStartAnchor, container, anchor);2956 hostInsert(fragmentEndAnchor, container, anchor);2957 // a fragment can only have array children2958 // since they are either generated by the compiler, or implicitly created2959 // from arrays.2960 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);2961 }2962 else {2963 if (patchFlag > 0 &&2964 patchFlag & 64 /* STABLE_FRAGMENT */ &&2965 dynamicChildren) {2966 // a stable fragment (template root or <template v-for>) doesn't need to2967 // patch children order, but it may contain dynamicChildren.2968 patchBlockChildren(n1.dynamicChildren, dynamicChildren, container, parentComponent, parentSuspense, isSVG);2969 }2970 else {2971 // keyed / unkeyed, or manual fragments.2972 // for keyed & unkeyed, since they are compiler generated from v-for,2973 // each child is guaranteed to be a block so the fragment will never2974 // have dynamicChildren.2975 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);2976 }2977 }2978 };2979 const processComponent = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {2980 if (n1 == null) {2981 if (n2.shapeFlag & 512 /* COMPONENT_KEPT_ALIVE */) {2982 parentComponent.ctx.activate(n2, container, anchor, isSVG, optimized);2983 }2984 else {2985 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2986 }2987 }2988 else {2989 updateComponent(n1, n2, parentComponent, optimized);2990 }2991 };2992 const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {2993 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent, parentSuspense));2994 if ( instance.type.__hmrId) {2995 registerHMR(instance);2996 }2997 {2998 pushWarningContext(initialVNode);2999 startMeasure(instance, `mount`);3000 }3001 // inject renderer internals for keepAlive3002 if (isKeepAlive(initialVNode)) {3003 instance.ctx.renderer = internals;3004 }3005 // resolve props and slots for setup context3006 {3007 startMeasure(instance, `init`);3008 }3009 setupComponent(instance);3010 {3011 endMeasure(instance, `init`);3012 }3013 // setup() is async. This component relies on async logic to be resolved3014 // before proceeding3015 if ( instance.asyncDep) {3016 if (!parentSuspense) {3017 warn('async setup() is used without a suspense boundary!');3018 return;3019 }3020 parentSuspense.registerDep(instance, setupRenderEffect);3021 // Give it a placeholder if this is not hydration3022 if (!initialVNode.el) {3023 const placeholder = (instance.subTree = createVNode(Comment));3024 processCommentNode(null, placeholder, container, anchor);3025 }3026 return;3027 }3028 setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized);3029 {3030 popWarningContext();3031 endMeasure(instance, `mount`);3032 }3033 };3034 const updateComponent = (n1, n2, parentComponent, optimized) => {3035 const instance = (n2.component = n1.component);3036 if (shouldUpdateComponent(n1, n2, parentComponent, optimized)) {3037 if (3038 instance.asyncDep &&3039 !instance.asyncResolved) {3040 // async & still pending - just update props and slots3041 // since the component's reactive effect for render isn't set-up yet3042 {3043 pushWarningContext(n2);3044 }3045 updateComponentPreRender(instance, n2, optimized);3046 {3047 popWarningContext();3048 }3049 return;3050 }3051 else {3052 // normal update3053 instance.next = n2;3054 // in case the child component is also queued, remove it to avoid3055 // double updating the same child component in the same flush.3056 invalidateJob(instance.update);3057 // instance.update is the reactive effect runner.3058 instance.update();3059 }3060 }3061 else {3062 // no update needed. just copy over properties3063 n2.component = n1.component;3064 n2.el = n1.el;3065 }3066 };3067 const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {3068 // create reactive effect for rendering3069 instance.update = effect(function componentEffect() {3070 if (!instance.isMounted) {3071 let vnodeHook;3072 const { el, props } = initialVNode;3073 const { bm, m, a, parent } = instance;3074 {3075 startMeasure(instance, `render`);3076 }3077 const subTree = (instance.subTree = renderComponentRoot(instance));3078 {3079 endMeasure(instance, `render`);3080 }3081 // beforeMount hook3082 if (bm) {3083 invokeArrayFns(bm);3084 }3085 // onVnodeBeforeMount3086 if ((vnodeHook = props && props.onVnodeBeforeMount)) {3087 invokeVNodeHook(vnodeHook, parent, initialVNode);3088 }3089 if (el && hydrateNode) {3090 {3091 startMeasure(instance, `hydrate`);3092 }3093 // vnode has adopted host node - perform hydration instead of mount.3094 hydrateNode(initialVNode.el, subTree, instance, parentSuspense);3095 {3096 endMeasure(instance, `hydrate`);3097 }3098 }3099 else {3100 {3101 startMeasure(instance, `patch`);3102 }3103 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);3104 {3105 endMeasure(instance, `patch`);3106 }3107 initialVNode.el = subTree.el;3108 }3109 // mounted hook3110 if (m) {3111 queuePostRenderEffect(m, parentSuspense);3112 }3113 // onVnodeMounted3114 if ((vnodeHook = props && props.onVnodeMounted)) {3115 queuePostRenderEffect(() => {3116 invokeVNodeHook(vnodeHook, parent, initialVNode);3117 }, parentSuspense);3118 }3119 // activated hook for keep-alive roots.3120 if (a &&3121 initialVNode.shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {3122 queuePostRenderEffect(a, parentSuspense);3123 }3124 instance.isMounted = true;3125 }3126 else {3127 // updateComponent3128 // This is triggered by mutation of component's own state (next: null)3129 // OR parent calling processComponent (next: VNode)3130 let { next, bu, u, parent, vnode } = instance;3131 let vnodeHook;3132 {3133 pushWarningContext(next || instance.vnode);3134 }3135 if (next) {3136 updateComponentPreRender(instance, next, optimized);3137 }3138 else {3139 next = vnode;3140 }3141 {3142 startMeasure(instance, `render`);3143 }3144 const nextTree = renderComponentRoot(instance);3145 {3146 endMeasure(instance, `render`);3147 }3148 const prevTree = instance.subTree;3149 instance.subTree = nextTree;3150 next.el = vnode.el;3151 // beforeUpdate hook3152 if (bu) {3153 invokeArrayFns(bu);3154 }3155 // onVnodeBeforeUpdate3156 if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {3157 invokeVNodeHook(vnodeHook, parent, next, vnode);3158 }3159 // reset refs3160 // only needed if previous patch had refs3161 if (instance.refs !== EMPTY_OBJ) {3162 instance.refs = {};3163 }3164 {3165 startMeasure(instance, `patch`);3166 }3167 patch(prevTree, nextTree, 3168 // parent may have changed if it's in a teleport3169 hostParentNode(prevTree.el), 3170 // anchor may have changed if it's in a fragment3171 getNextHostNode(prevTree), instance, parentSuspense, isSVG);3172 {3173 endMeasure(instance, `patch`);3174 }3175 next.el = nextTree.el;3176 if (next === null) {3177 // self-triggered update. In case of HOC, update parent component3178 // vnode el. HOC is indicated by parent instance's subTree pointing3179 // to child component's vnode3180 updateHOCHostEl(instance, nextTree.el);3181 }3182 // updated hook3183 if (u) {3184 queuePostRenderEffect(u, parentSuspense);3185 }3186 // onVnodeUpdated3187 if ((vnodeHook = next.props && next.props.onVnodeUpdated)) {3188 queuePostRenderEffect(() => {3189 invokeVNodeHook(vnodeHook, parent, next, vnode);3190 }, parentSuspense);3191 }3192 {3193 popWarningContext();3194 }3195 }3196 }, createDevEffectOptions(instance) );3197 };3198 const updateComponentPreRender = (instance, nextVNode, optimized) => {3199 nextVNode.component = instance;3200 const prevProps = instance.vnode.props;3201 instance.vnode = nextVNode;3202 instance.next = null;3203 updateProps(instance, nextVNode.props, prevProps, optimized);3204 updateSlots(instance, nextVNode.children);3205 };3206 const patchChildren = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized = false) => {3207 const c1 = n1 && n1.children;3208 const prevShapeFlag = n1 ? n1.shapeFlag : 0;3209 const c2 = n2.children;3210 const { patchFlag, shapeFlag } = n2;3211 // fast path3212 if (patchFlag > 0) {3213 if (patchFlag & 128 /* KEYED_FRAGMENT */) {3214 // this could be either fully-keyed or mixed (some keyed some not)3215 // presence of patchFlag means children are guaranteed to be arrays3216 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);3217 return;3218 }3219 else if (patchFlag & 256 /* UNKEYED_FRAGMENT */) {3220 // unkeyed3221 patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);3222 return;3223 }3224 }3225 // children has 3 possibilities: text, array or no children.3226 if (shapeFlag & 8 /* TEXT_CHILDREN */) {3227 // text children fast path3228 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {3229 unmountChildren(c1, parentComponent, parentSuspense);3230 }3231 if (c2 !== c1) {3232 hostSetElementText(container, c2);3233 }3234 }3235 else {3236 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {3237 // prev children was array3238 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {3239 // two arrays, cannot assume anything, do full diff3240 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);3241 }3242 else {3243 // no new children, just unmount old3244 unmountChildren(c1, parentComponent, parentSuspense, true);3245 }3246 }3247 else {3248 // prev children was text OR null3249 // new children is array OR null3250 if (prevShapeFlag & 8 /* TEXT_CHILDREN */) {3251 hostSetElementText(container, '');3252 }3253 // mount new if array3254 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {3255 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);3256 }3257 }3258 }3259 };3260 const patchUnkeyedChildren = (c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {3261 c1 = c1 || EMPTY_ARR;3262 c2 = c2 || EMPTY_ARR;3263 const oldLength = c1.length;3264 const newLength = c2.length;3265 const commonLength = Math.min(oldLength, newLength);3266 let i;3267 for (i = 0; i < commonLength; i++) {3268 const nextChild = (c2[i] = optimized3269 ? cloneIfMounted(c2[i])3270 : normalizeVNode(c2[i]));3271 patch(c1[i], nextChild, container, null, parentComponent, parentSuspense, isSVG, optimized);3272 }3273 if (oldLength > newLength) {3274 // remove old3275 unmountChildren(c1, parentComponent, parentSuspense, true, commonLength);3276 }3277 else {3278 // mount new3279 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, commonLength);3280 }3281 };3282 // can be all-keyed or mixed3283 const patchKeyedChildren = (c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) => {3284 let i = 0;3285 const l2 = c2.length;3286 let e1 = c1.length - 1; // prev ending index3287 let e2 = l2 - 1; // next ending index3288 // 1. sync from start3289 // (a b) c3290 // (a b) d e3291 while (i <= e1 && i <= e2) {3292 const n1 = c1[i];3293 const n2 = (c2[i] = optimized3294 ? cloneIfMounted(c2[i])3295 : normalizeVNode(c2[i]));3296 if (isSameVNodeType(n1, n2)) {3297 patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);3298 }3299 else {3300 break;3301 }3302 i++;3303 }3304 // 2. sync from end3305 // a (b c)3306 // d e (b c)3307 while (i <= e1 && i <= e2) {3308 const n1 = c1[e1];3309 const n2 = (c2[e2] = optimized3310 ? cloneIfMounted(c2[e2])3311 : normalizeVNode(c2[e2]));3312 if (isSameVNodeType(n1, n2)) {3313 patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);3314 }3315 else {3316 break;3317 }3318 e1--;3319 e2--;3320 }3321 // 3. common sequence + mount3322 // (a b)3323 // (a b) c3324 // i = 2, e1 = 1, e2 = 23325 // (a b)3326 // c (a b)3327 // i = 0, e1 = -1, e2 = 03328 if (i > e1) {3329 if (i <= e2) {3330 const nextPos = e2 + 1;3331 const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;3332 while (i <= e2) {3333 patch(null, (c2[i] = optimized3334 ? cloneIfMounted(c2[i])3335 : normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);3336 i++;3337 }3338 }3339 }3340 // 4. common sequence + unmount3341 // (a b) c3342 // (a b)3343 // i = 2, e1 = 2, e2 = 13344 // a (b c)3345 // (b c)3346 // i = 0, e1 = 0, e2 = -13347 else if (i > e2) {3348 while (i <= e1) {3349 unmount(c1[i], parentComponent, parentSuspense, true);3350 i++;3351 }3352 }3353 // 5. unknown sequence3354 // [i ... e1 + 1]: a b [c d e] f g3355 // [i ... e2 + 1]: a b [e d c h] f g3356 // i = 2, e1 = 4, e2 = 53357 else {3358 const s1 = i; // prev starting index3359 const s2 = i; // next starting index3360 // 5.1 build key:index map for newChildren3361 const keyToNewIndexMap = new Map();3362 for (i = s2; i <= e2; i++) {3363 const nextChild = (c2[i] = optimized3364 ? cloneIfMounted(c2[i])3365 : normalizeVNode(c2[i]));3366 if (nextChild.key != null) {3367 if ( keyToNewIndexMap.has(nextChild.key)) {3368 warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);3369 }3370 keyToNewIndexMap.set(nextChild.key, i);3371 }3372 }3373 // 5.2 loop through old children left to be patched and try to patch3374 // matching nodes & remove nodes that are no longer present3375 let j;3376 let patched = 0;3377 const toBePatched = e2 - s2 + 1;3378 let moved = false;3379 // used to track whether any node has moved3380 let maxNewIndexSoFar = 0;3381 // works as Map<newIndex, oldIndex>3382 // Note that oldIndex is offset by +13383 // and oldIndex = 0 is a special value indicating the new node has3384 // no corresponding old node.3385 // used for determining longest stable subsequence3386 const newIndexToOldIndexMap = new Array(toBePatched);3387 for (i = 0; i < toBePatched; i++)3388 newIndexToOldIndexMap[i] = 0;3389 for (i = s1; i <= e1; i++) {3390 const prevChild = c1[i];3391 if (patched >= toBePatched) {3392 // all new children have been patched so this can only be a removal3393 unmount(prevChild, parentComponent, parentSuspense, true);3394 continue;3395 }3396 let newIndex;3397 if (prevChild.key != null) {3398 newIndex = keyToNewIndexMap.get(prevChild.key);3399 }3400 else {3401 // key-less node, try to locate a key-less node of the same type3402 for (j = s2; j <= e2; j++) {3403 if (newIndexToOldIndexMap[j - s2] === 0 &&3404 isSameVNodeType(prevChild, c2[j])) {3405 newIndex = j;3406 break;3407 }3408 }3409 }3410 if (newIndex === undefined) {3411 unmount(prevChild, parentComponent, parentSuspense, true);3412 }3413 else {3414 newIndexToOldIndexMap[newIndex - s2] = i + 1;3415 if (newIndex >= maxNewIndexSoFar) {3416 maxNewIndexSoFar = newIndex;3417 }3418 else {3419 moved = true;3420 }3421 patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);3422 patched++;3423 }3424 }3425 // 5.3 move and mount3426 // generate longest stable subsequence only when nodes have moved3427 const increasingNewIndexSequence = moved3428 ? getSequence(newIndexToOldIndexMap)3429 : EMPTY_ARR;3430 j = increasingNewIndexSequence.length - 1;3431 // looping backwards so that we can use last patched node as anchor3432 for (i = toBePatched - 1; i >= 0; i--) {3433 const nextIndex = s2 + i;3434 const nextChild = c2[nextIndex];3435 const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : parentAnchor;3436 if (newIndexToOldIndexMap[i] === 0) {3437 // mount new3438 patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);3439 }3440 else if (moved) {3441 // move if:3442 // There is no stable subsequence (e.g. a reverse)3443 // OR current node is not among the stable sequence3444 if (j < 0 || i !== increasingNewIndexSequence[j]) {3445 move(nextChild, container, anchor, 2 /* REORDER */);3446 }3447 else {3448 j--;3449 }3450 }3451 }3452 }3453 };3454 const move = (vnode, container, anchor, moveType, parentSuspense = null) => {3455 const { el, type, transition, children, shapeFlag } = vnode;3456 if (shapeFlag & 6 /* COMPONENT */) {3457 move(vnode.component.subTree, container, anchor, moveType);3458 return;3459 }3460 if ( shapeFlag & 128 /* SUSPENSE */) {3461 vnode.suspense.move(container, anchor, moveType);3462 return;3463 }3464 if (shapeFlag & 64 /* TELEPORT */) {3465 type.move(vnode, container, anchor, internals);3466 return;3467 }3468 if (type === Fragment) {3469 hostInsert(el, container, anchor);3470 for (let i = 0; i < children.length; i++) {3471 move(children[i], container, anchor, moveType);3472 }3473 hostInsert(vnode.anchor, container, anchor);3474 return;3475 }3476 // single nodes3477 const needTransition = moveType !== 2 /* REORDER */ &&3478 shapeFlag & 1 /* ELEMENT */ &&3479 transition;3480 if (needTransition) {3481 if (moveType === 0 /* ENTER */) {3482 transition.beforeEnter(el);3483 hostInsert(el, container, anchor);3484 queuePostRenderEffect(() => transition.enter(el), parentSuspense);3485 }3486 else {3487 const { leave, delayLeave, afterLeave } = transition;3488 const remove = () => hostInsert(el, container, anchor);3489 const performLeave = () => {3490 leave(el, () => {3491 remove();3492 afterLeave && afterLeave();3493 });3494 };3495 if (delayLeave) {3496 delayLeave(el, remove, performLeave);3497 }3498 else {3499 performLeave();3500 }3501 }3502 }3503 else {3504 hostInsert(el, container, anchor);3505 }3506 };3507 const unmount = (vnode, parentComponent, parentSuspense, doRemove = false) => {3508 const { props, ref, children, dynamicChildren, shapeFlag, dirs } = vnode;3509 const shouldInvokeDirs = shapeFlag & 1 /* ELEMENT */ && dirs;3510 const shouldKeepAlive = shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */;3511 let vnodeHook;3512 // unset ref3513 if (ref != null && parentComponent) {3514 setRef(ref, null, parentComponent, null);3515 }3516 if ((vnodeHook = props && props.onVnodeBeforeUnmount) && !shouldKeepAlive) {3517 invokeVNodeHook(vnodeHook, parentComponent, vnode);3518 }3519 if (shapeFlag & 6 /* COMPONENT */) {3520 if (shouldKeepAlive) {3521 parentComponent.ctx.deactivate(vnode);3522 }3523 else {3524 unmountComponent(vnode.component, parentSuspense, doRemove);3525 }3526 }3527 else {3528 if ( shapeFlag & 128 /* SUSPENSE */) {3529 vnode.suspense.unmount(parentSuspense, doRemove);3530 return;3531 }3532 if (shouldInvokeDirs) {3533 invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount');3534 }3535 if (dynamicChildren) {3536 // fast path for block nodes: only need to unmount dynamic children.3537 unmountChildren(dynamicChildren, parentComponent, parentSuspense);3538 }3539 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {3540 unmountChildren(children, parentComponent, parentSuspense);3541 }3542 // an unmounted teleport should always remove its children3543 if (shapeFlag & 64 /* TELEPORT */) {3544 vnode.type.remove(vnode, internals);3545 }3546 if (doRemove) {3547 remove(vnode);3548 }3549 }3550 if (((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) &&3551 !shouldKeepAlive) {3552 queuePostRenderEffect(() => {3553 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);3554 shouldInvokeDirs &&3555 invokeDirectiveHook(vnode, null, parentComponent, 'unmounted');3556 }, parentSuspense);3557 }3558 };3559 const remove = vnode => {3560 const { type, el, anchor, transition } = vnode;3561 if (type === Fragment) {3562 removeFragment(el, anchor);3563 return;3564 }3565 const performRemove = () => {3566 hostRemove(el);3567 if (transition && !transition.persisted && transition.afterLeave) {3568 transition.afterLeave();3569 }3570 };3571 if (vnode.shapeFlag & 1 /* ELEMENT */ &&3572 transition &&3573 !transition.persisted) {3574 const { leave, delayLeave } = transition;3575 const performLeave = () => leave(el, performRemove);3576 if (delayLeave) {3577 delayLeave(vnode.el, performRemove, performLeave);3578 }3579 else {3580 performLeave();3581 }3582 }3583 else {3584 performRemove();3585 }3586 };3587 const removeFragment = (cur, end) => {3588 // For fragments, directly remove all contained DOM nodes.3589 // (fragment child nodes cannot have transition)3590 let next;3591 while (cur !== end) {3592 next = hostNextSibling(cur);3593 hostRemove(cur);3594 cur = next;3595 }3596 hostRemove(end);3597 };3598 const unmountComponent = (instance, parentSuspense, doRemove) => {3599 if ( instance.type.__hmrId) {3600 unregisterHMR(instance);3601 }3602 const { bum, effects, update, subTree, um, da, isDeactivated } = instance;3603 // beforeUnmount hook3604 if (bum) {3605 invokeArrayFns(bum);3606 }3607 if (effects) {3608 for (let i = 0; i < effects.length; i++) {3609 stop(effects[i]);3610 }3611 }3612 // update may be null if a component is unmounted before its async3613 // setup has resolved.3614 if (update) {3615 stop(update);3616 unmount(subTree, instance, parentSuspense, doRemove);3617 }3618 // unmounted hook3619 if (um) {3620 queuePostRenderEffect(um, parentSuspense);3621 }3622 // deactivated hook3623 if (da &&3624 !isDeactivated &&3625 instance.vnode.shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {3626 queuePostRenderEffect(da, parentSuspense);3627 }3628 queuePostRenderEffect(() => {3629 instance.isUnmounted = true;3630 }, parentSuspense);3631 // A component with async dep inside a pending suspense is unmounted before3632 // its async dep resolves. This should remove the dep from the suspense, and3633 // cause the suspense to resolve immediately if that was the last dep.3634 if (3635 parentSuspense &&3636 !parentSuspense.isResolved &&3637 !parentSuspense.isUnmounted &&3638 instance.asyncDep &&3639 !instance.asyncResolved) {3640 parentSuspense.deps--;3641 if (parentSuspense.deps === 0) {3642 parentSuspense.resolve();3643 }3644 }3645 };3646 const unmountChildren = (children, parentComponent, parentSuspense, doRemove = false, start = 0) => {3647 for (let i = start; i < children.length; i++) {3648 unmount(children[i], parentComponent, parentSuspense, doRemove);3649 }3650 };3651 const getNextHostNode = vnode => {3652 if (vnode.shapeFlag & 6 /* COMPONENT */) {3653 return getNextHostNode(vnode.component.subTree);3654 }3655 if ( vnode.shapeFlag & 128 /* SUSPENSE */) {3656 return vnode.suspense.next();3657 }3658 return hostNextSibling((vnode.anchor || vnode.el));3659 };3660 const setRef = (rawRef, oldRawRef, parent, value) => {3661 const [owner, ref] = rawRef;3662 if ( !owner) {3663 warn(`Missing ref owner context. ref cannot be used on hoisted vnodes. ` +3664 `A vnode with ref must be created inside the render function.`);3665 return;3666 }3667 const oldRef = oldRawRef && oldRawRef[1];3668 const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs;3669 const setupState = owner.setupState;3670 // unset old ref3671 if (oldRef != null && oldRef !== ref) {3672 if (isString(oldRef)) {3673 refs[oldRef] = null;3674 if (hasOwn(setupState, oldRef)) {3675 setupState[oldRef] = null;3676 }3677 }3678 else if (isRef(oldRef)) {3679 oldRef.value = null;3680 }3681 }3682 if (isString(ref)) {3683 refs[ref] = value;3684 if (hasOwn(setupState, ref)) {3685 setupState[ref] = value;3686 }3687 }3688 else if (isRef(ref)) {3689 ref.value = value;3690 }3691 else if (isFunction(ref)) {3692 callWithErrorHandling(ref, parent, 12 /* FUNCTION_REF */, [value, refs]);3693 }3694 else {3695 warn('Invalid template ref type:', value, `(${typeof value})`);3696 }3697 };3698 const render = (vnode, container) => {3699 if (vnode == null) {3700 if (container._vnode) {3701 unmount(container._vnode, null, null, true);3702 }3703 }3704 else {3705 patch(container._vnode || null, vnode, container);3706 }3707 flushPostFlushCbs();3708 container._vnode = vnode;3709 };3710 const internals = {3711 p: patch,3712 um: unmount,3713 m: move,3714 r: remove,3715 mt: mountComponent,3716 mc: mountChildren,3717 pc: patchChildren,3718 pbc: patchBlockChildren,3719 n: getNextHostNode,3720 o: options3721 };3722 let hydrate;3723 let hydrateNode;3724 if (createHydrationFns) {3725 [hydrate, hydrateNode] = createHydrationFns(internals);3726 }3727 return {3728 render,3729 hydrate,3730 createApp: createAppAPI(render, hydrate)3731 };3732}3733function invokeVNodeHook(hook, instance, vnode, prevVNode = null) {3734 callWithAsyncErrorHandling(hook, instance, 7 /* VNODE_HOOK */, [3735 vnode,3736 prevVNode3737 ]);3738}3739// https://en.wikipedia.org/wiki/Longest_increasing_subsequence3740function getSequence(arr) {3741 const p = arr.slice();3742 const result = [0];3743 let i, j, u, v, c;3744 const len = arr.length;3745 for (i = 0; i < len; i++) {3746 const arrI = arr[i];3747 if (arrI !== 0) {3748 j = result[result.length - 1];3749 if (arr[j] < arrI) {3750 p[i] = j;3751 result.push(i);3752 continue;3753 }3754 u = 0;3755 v = result.length - 1;3756 while (u < v) {3757 c = ((u + v) / 2) | 0;3758 if (arr[result[c]] < arrI) {3759 u = c + 1;3760 }3761 else {3762 v = c;3763 }3764 }3765 if (arrI < arr[result[u]]) {3766 if (u > 0) {3767 p[i] = result[u - 1];3768 }3769 result[u] = i;3770 }3771 }3772 }3773 u = result.length;3774 v = result[u - 1];3775 while (u-- > 0) {3776 result[u] = v;3777 v = p[v];3778 }3779 return result;3780}3781const isKeepAlive = (vnode) => vnode.type.__isKeepAlive;3782function onActivated(hook, target) {3783 registerKeepAliveHook(hook, "a" /* ACTIVATED */, target);3784}3785function onDeactivated(hook, target) {3786 registerKeepAliveHook(hook, "da" /* DEACTIVATED */, target);3787}3788function registerKeepAliveHook(hook, type, target = currentInstance) {3789 // cache the deactivate branch check wrapper for injected hooks so the same3790 // hook can be properly deduped by the scheduler. "__wdc" stands for "with3791 // deactivation check".3792 const wrappedHook = hook.__wdc ||3793 (hook.__wdc = () => {3794 // only fire the hook if the target instance is NOT in a deactivated branch.3795 let current = target;3796 while (current) {3797 if (current.isDeactivated) {3798 return;3799 }3800 current = current.parent;3801 }3802 hook();3803 });3804 injectHook(type, wrappedHook, target);3805 // In addition to registering it on the target instance, we walk up the parent3806 // chain and register it on all ancestor instances that are keep-alive roots.3807 // This avoids the need to walk the entire component tree when invoking these3808 // hooks, and more importantly, avoids the need to track child components in3809 // arrays.3810 if (target) {3811 let current = target.parent;3812 while (current && current.parent) {3813 if (isKeepAlive(current.parent.vnode)) {3814 injectToKeepAliveRoot(wrappedHook, type, target, current);3815 }3816 current = current.parent;3817 }3818 }3819}3820function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) {3821 injectHook(type, hook, keepAliveRoot, true /* prepend */);3822 onUnmounted(() => {3823 remove(keepAliveRoot[type], hook);3824 }, target);3825}3826function injectHook(type, hook, target = currentInstance, prepend = false) {3827 if (target) {3828 const hooks = target[type] || (target[type] = []);3829 // cache the error handling wrapper for injected hooks so the same hook3830 // can be properly deduped by the scheduler. "__weh" stands for "with error3831 // handling".3832 const wrappedHook = hook.__weh ||3833 (hook.__weh = (...args) => {3834 if (target.isUnmounted) {3835 return;3836 }3837 // disable tracking inside all lifecycle hooks3838 // since they can potentially be called inside effects.3839 pauseTracking();3840 // Set currentInstance during hook invocation.3841 // This assumes the hook does not synchronously trigger other hooks, which3842 // can only be false when the user does something really funky.3843 setCurrentInstance(target);3844 const res = callWithAsyncErrorHandling(hook, target, type, args);3845 setCurrentInstance(null);3846 resetTracking();3847 return res;3848 });3849 if (prepend) {3850 hooks.unshift(wrappedHook);3851 }3852 else {3853 hooks.push(wrappedHook);3854 }3855 }3856 else {3857 const apiName = `on${capitalize(ErrorTypeStrings[type].replace(/ hook$/, ''))}`;3858 warn(`${apiName} is called when there is no active component instance to be ` +3859 `associated with. ` +3860 `Lifecycle injection APIs can only be used during execution of setup().` +3861 ( ` If you are using async setup(), make sure to register lifecycle ` +3862 `hooks before the first await statement.`3863 ));3864 }3865}3866const createHook = (lifecycle) => (hook, target = currentInstance) => 3867// post-create lifecycle registrations are noops during SSR3868!isInSSRComponentSetup && injectHook(lifecycle, hook, target);3869const onBeforeMount = createHook("bm" /* BEFORE_MOUNT */);3870const onMounted = createHook("m" /* MOUNTED */);3871const onBeforeUpdate = createHook("bu" /* BEFORE_UPDATE */);3872const onUpdated = createHook("u" /* UPDATED */);3873const onBeforeUnmount = createHook("bum" /* BEFORE_UNMOUNT */);3874const onUnmounted = createHook("um" /* UNMOUNTED */);3875const onRenderTriggered = createHook("rtg" /* RENDER_TRIGGERED */);3876const onRenderTracked = createHook("rtc" /* RENDER_TRACKED */);3877const onErrorCaptured = (hook, target = currentInstance) => {3878 injectHook("ec" /* ERROR_CAPTURED */, hook, target);3879};3880const invoke = (fn) => fn();3881// initial value for watchers to trigger on undefined initial values3882const INITIAL_WATCHER_VALUE = {};3883// implementation3884function watch(source, cb, options) {3885 if ( !isFunction(cb)) {3886 warn(`\`watch(fn, options?)\` signature has been moved to a separate API. ` +3887 `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +3888 `supports \`watch(source, cb, options?) signature.`);3889 }3890 return doWatch(source, cb, options);3891}3892function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ) {3893 if ( !cb) {3894 if (immediate !== undefined) {3895 warn(`watch() "immediate" option is only respected when using the ` +3896 `watch(source, callback, options?) signature.`);3897 }3898 if (deep !== undefined) {3899 warn(`watch() "deep" option is only respected when using the ` +3900 `watch(source, callback, options?) signature.`);3901 }3902 }3903 const instance = currentInstance;3904 let getter;3905 if (isArray(source)) {3906 getter = () => source.map(s => isRef(s)3907 ? s.value3908 : callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */));3909 }3910 else if (isRef(source)) {3911 getter = () => source.value;3912 }3913 else if (isReactive(source)) {3914 getter = () => source;3915 deep = true;3916 }3917 else if (isFunction(source)) {3918 if (cb) {3919 // getter with cb3920 getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */);3921 }3922 else {3923 // no cb -> simple effect3924 getter = () => {3925 if (instance && instance.isUnmounted) {3926 return;3927 }3928 if (cleanup) {3929 cleanup();3930 }3931 return callWithErrorHandling(source, instance, 3 /* WATCH_CALLBACK */, [onInvalidate]);3932 };3933 }3934 }3935 else {3936 getter = NOOP;3937 3938 warn(`Invalid watch source: `, source, `A watch source can only be a getter/effect function, a ref, ` +3939 `a reactive object, or an array of these types.`);3940 }3941 if (cb && deep) {3942 const baseGetter = getter;3943 getter = () => traverse(baseGetter());3944 }3945 let cleanup;3946 const onInvalidate = (fn) => {3947 cleanup = runner.options.onStop = () => {3948 callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */);3949 };3950 };3951 let oldValue = isArray(source) ? [] : INITIAL_WATCHER_VALUE;3952 const applyCb = cb3953 ? () => {3954 if (instance && instance.isUnmounted) {3955 return;3956 }3957 const newValue = runner();3958 if (deep || hasChanged(newValue, oldValue)) {3959 // cleanup before running cb again3960 if (cleanup) {3961 cleanup();3962 }3963 callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [3964 newValue,3965 // pass undefined as the old value when it's changed for the first time3966 oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,3967 onInvalidate3968 ]);3969 oldValue = newValue;3970 }3971 }3972 : void 0;3973 let scheduler;3974 if (flush === 'sync') {3975 scheduler = invoke;3976 }3977 else if (flush === 'pre') {3978 scheduler = job => {3979 if (!instance || instance.isMounted) {3980 queueJob(job);3981 }3982 else {3983 // with 'pre' option, the first call must happen before3984 // the component is mounted so it is called synchronously.3985 job();3986 }3987 };3988 }3989 else {3990 scheduler = job => queuePostRenderEffect(job, instance && instance.suspense);3991 }3992 const runner = effect(getter, {3993 lazy: true,3994 // so it runs before component update effects in pre flush mode3995 computed: true,3996 onTrack,3997 onTrigger,3998 scheduler: applyCb ? () => scheduler(applyCb) : scheduler3999 });4000 recordInstanceBoundEffect(runner);4001 // initial run4002 if (applyCb) {4003 if (immediate) {4004 applyCb();4005 }4006 else {4007 oldValue = runner();4008 }4009 }4010 else {4011 runner();4012 }4013 return () => {4014 stop(runner);4015 if (instance) {4016 remove(instance.effects, runner);4017 }4018 };4019}4020// this.$watch4021function instanceWatch(source, cb, options) {4022 const publicThis = this.proxy;4023 const getter = isString(source)4024 ? () => publicThis[source]4025 : source.bind(publicThis);4026 const stop = watch(getter, cb.bind(publicThis), options);4027 onBeforeUnmount(stop, this);4028 return stop;4029}4030function traverse(value, seen = new Set()) {4031 if (!isObject(value) || seen.has(value)) {4032 return value;4033 }4034 seen.add(value);4035 if (isArray(value)) {4036 for (let i = 0; i < value.length; i++) {4037 traverse(value[i], seen);4038 }4039 }4040 else if (value instanceof Map) {4041 value.forEach((v, key) => {4042 // to register mutation dep for existing keys4043 traverse(value.get(key), seen);4044 });4045 }4046 else if (value instanceof Set) {4047 value.forEach(v => {4048 traverse(v, seen);4049 });4050 }4051 else {4052 for (const key in value) {4053 traverse(value[key], seen);4054 }4055 }4056 return value;4057}4058function provide(key, value) {4059 if (!currentInstance) {4060 {4061 warn(`provide() can only be used inside setup().`);4062 }4063 }4064 else {4065 let provides = currentInstance.provides;4066 // by default an instance inherits its parent's provides object4067 // but when it needs to provide values of its own, it creates its4068 // own provides object using parent provides object as prototype.4069 // this way in `inject` we can simply look up injections from direct4070 // parent and let the prototype chain do the work.4071 const parentProvides = currentInstance.parent && currentInstance.parent.provides;4072 if (parentProvides === provides) {4073 provides = currentInstance.provides = Object.create(parentProvides);4074 }4075 // TS doesn't allow symbol as index type4076 provides[key] = value;4077 }4078}4079function inject(key, defaultValue) {4080 // fallback to `currentRenderingInstance` so that this can be called in4081 // a functional component4082 const instance = currentInstance || currentRenderingInstance;4083 if (instance) {4084 const provides = instance.provides;4085 if (key in provides) {4086 // TS doesn't allow symbol as index type4087 return provides[key];4088 }4089 else if (arguments.length > 1) {4090 return defaultValue;4091 }4092 else {4093 warn(`injection "${String(key)}" not found.`);4094 }4095 }4096 else {4097 warn(`inject() can only be used inside setup() or functional components.`);4098 }4099}4100function createDuplicateChecker() {4101 const cache = Object.create(null);4102 return (type, key) => {4103 if (cache[key]) {4104 warn(`${type} property "${key}" is already defined in ${cache[key]}.`);4105 }4106 else {4107 cache[key] = type;4108 }4109 };4110}4111function applyOptions(instance, options, deferredData = [], deferredWatch = [], asMixin = false) {4112 const { 4113 // composition4114 mixins, extends: extendsOptions, 4115 // state4116 props: propsOptions, data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions, 4117 // assets4118 components, directives, 4119 // lifecycle4120 beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeUnmount, unmounted, renderTracked, renderTriggered, errorCaptured } = options;4121 const publicThis = instance.proxy;4122 const ctx = instance.ctx;4123 const globalMixins = instance.appContext.mixins;4124 // call it only during dev4125 // applyOptions is called non-as-mixin once per instance4126 if (!asMixin) {4127 callSyncHook('beforeCreate', options, publicThis, globalMixins);4128 // global mixins are applied first4129 applyMixins(instance, globalMixins, deferredData, deferredWatch);4130 }4131 // extending a base component...4132 if (extendsOptions) {4133 applyOptions(instance, extendsOptions, deferredData, deferredWatch, true);4134 }4135 // local mixins4136 if (mixins) {4137 applyMixins(instance, mixins, deferredData, deferredWatch);4138 }4139 const checkDuplicateProperties = createDuplicateChecker() ;4140 if ( propsOptions) {4141 for (const key in normalizePropsOptions(propsOptions)[0]) {4142 checkDuplicateProperties("Props" /* PROPS */, key);4143 }4144 }4145 // options initialization order (to be consistent with Vue 2):4146 // - props (already done outside of this function)4147 // - inject4148 // - methods4149 // - data (deferred since it relies on `this` access)4150 // - computed4151 // - watch (deferred since it relies on `this` access)4152 if (injectOptions) {4153 if (isArray(injectOptions)) {4154 for (let i = 0; i < injectOptions.length; i++) {4155 const key = injectOptions[i];4156 ctx[key] = inject(key);4157 {4158 checkDuplicateProperties("Inject" /* INJECT */, key);4159 }4160 }4161 }4162 else {4163 for (const key in injectOptions) {4164 const opt = injectOptions[key];4165 if (isObject(opt)) {4166 ctx[key] = inject(opt.from, opt.default);4167 }4168 else {4169 ctx[key] = inject(opt);4170 }4171 {4172 checkDuplicateProperties("Inject" /* INJECT */, key);4173 }4174 }4175 }4176 }4177 if (methods) {4178 for (const key in methods) {4179 const methodHandler = methods[key];4180 if (isFunction(methodHandler)) {4181 ctx[key] = methodHandler.bind(publicThis);4182 {4183 checkDuplicateProperties("Methods" /* METHODS */, key);4184 }4185 }4186 else {4187 warn(`Method "${key}" has type "${typeof methodHandler}" in the component definition. ` +4188 `Did you reference the function correctly?`);4189 }4190 }4191 }4192 if (dataOptions) {4193 if ( !isFunction(dataOptions)) {4194 warn(`The data option must be a function. ` +4195 `Plain object usage is no longer supported.`);4196 }4197 if (asMixin) {4198 deferredData.push(dataOptions);4199 }4200 else {4201 resolveData(instance, dataOptions, publicThis);4202 }4203 }4204 if (!asMixin) {4205 if (deferredData.length) {4206 deferredData.forEach(dataFn => resolveData(instance, dataFn, publicThis));4207 }4208 {4209 const rawData = toRaw(instance.data);4210 for (const key in rawData) {4211 checkDuplicateProperties("Data" /* DATA */, key);4212 // expose data on ctx during dev4213 if (key[0] !== '$' && key[0] !== '_') {4214 Object.defineProperty(ctx, key, {4215 configurable: true,4216 enumerable: true,4217 get: () => rawData[key],4218 set: NOOP4219 });4220 }4221 }4222 }4223 }4224 if (computedOptions) {4225 for (const key in computedOptions) {4226 const opt = computedOptions[key];4227 const get = isFunction(opt)4228 ? opt.bind(publicThis, publicThis)4229 : isFunction(opt.get)4230 ? opt.get.bind(publicThis, publicThis)4231 : NOOP;4232 if ( get === NOOP) {4233 warn(`Computed property "${key}" has no getter.`);4234 }4235 const set = !isFunction(opt) && isFunction(opt.set)4236 ? opt.set.bind(publicThis)4237 : () => {4238 warn(`Write operation failed: computed property "${key}" is readonly.`);4239 }4240 ;4241 const c = computed$1({4242 get,4243 set4244 });4245 Object.defineProperty(ctx, key, {4246 enumerable: true,4247 configurable: true,4248 get: () => c.value,4249 set: v => (c.value = v)4250 });4251 {4252 checkDuplicateProperties("Computed" /* COMPUTED */, key);4253 }4254 }4255 }4256 if (watchOptions) {4257 deferredWatch.push(watchOptions);4258 }4259 if (!asMixin && deferredWatch.length) {4260 deferredWatch.forEach(watchOptions => {4261 for (const key in watchOptions) {4262 createWatcher(watchOptions[key], ctx, publicThis, key);4263 }4264 });4265 }4266 if (provideOptions) {4267 const provides = isFunction(provideOptions)4268 ? provideOptions.call(publicThis)4269 : provideOptions;4270 for (const key in provides) {4271 provide(key, provides[key]);4272 }4273 }4274 // asset options4275 if (components) {4276 extend(instance.components, components);4277 }4278 if (directives) {4279 extend(instance.directives, directives);4280 }4281 // lifecycle options4282 if (!asMixin) {4283 callSyncHook('created', options, publicThis, globalMixins);4284 }4285 if (beforeMount) {4286 onBeforeMount(beforeMount.bind(publicThis));4287 }4288 if (mounted) {4289 onMounted(mounted.bind(publicThis));4290 }4291 if (beforeUpdate) {4292 onBeforeUpdate(beforeUpdate.bind(publicThis));4293 }4294 if (updated) {4295 onUpdated(updated.bind(publicThis));4296 }4297 if (activated) {4298 onActivated(activated.bind(publicThis));4299 }4300 if (deactivated) {4301 onDeactivated(deactivated.bind(publicThis));4302 }4303 if (errorCaptured) {4304 onErrorCaptured(errorCaptured.bind(publicThis));4305 }4306 if (renderTracked) {4307 onRenderTracked(renderTracked.bind(publicThis));4308 }4309 if (renderTriggered) {4310 onRenderTriggered(renderTriggered.bind(publicThis));4311 }4312 if (beforeUnmount) {4313 onBeforeUnmount(beforeUnmount.bind(publicThis));4314 }4315 if (unmounted) {4316 onUnmounted(unmounted.bind(publicThis));4317 }4318}4319function callSyncHook(name, options, ctx, globalMixins) {4320 callHookFromMixins(name, globalMixins, ctx);4321 const baseHook = options.extends && options.extends[name];4322 if (baseHook) {4323 baseHook.call(ctx);4324 }4325 const mixins = options.mixins;4326 if (mixins) {4327 callHookFromMixins(name, mixins, ctx);4328 }4329 const selfHook = options[name];4330 if (selfHook) {4331 selfHook.call(ctx);4332 }4333}4334function callHookFromMixins(name, mixins, ctx) {4335 for (let i = 0; i < mixins.length; i++) {4336 const fn = mixins[i][name];4337 if (fn) {4338 fn.call(ctx);4339 }4340 }4341}4342function applyMixins(instance, mixins, deferredData, deferredWatch) {4343 for (let i = 0; i < mixins.length; i++) {4344 applyOptions(instance, mixins[i], deferredData, deferredWatch, true);4345 }4346}4347function resolveData(instance, dataFn, publicThis) {4348 const data = dataFn.call(publicThis, publicThis);4349 if ( isPromise(data)) {4350 warn(`data() returned a Promise - note data() cannot be async; If you ` +4351 `intend to perform data fetching before component renders, use ` +4352 `async setup() + <Suspense>.`);4353 }4354 if (!isObject(data)) {4355 warn(`data() should return an object.`);4356 }4357 else if (instance.data === EMPTY_OBJ) {4358 instance.data = reactive(data);4359 }4360 else {4361 // existing data: this is a mixin or extends.4362 extend(instance.data, data);4363 }4364}4365function createWatcher(raw, ctx, publicThis, key) {4366 const getter = () => publicThis[key];4367 if (isString(raw)) {4368 const handler = ctx[raw];4369 if (isFunction(handler)) {4370 watch(getter, handler);4371 }4372 else {4373 warn(`Invalid watch handler specified by key "${raw}"`, handler);4374 }4375 }4376 else if (isFunction(raw)) {4377 watch(getter, raw.bind(publicThis));4378 }4379 else if (isObject(raw)) {4380 if (isArray(raw)) {4381 raw.forEach(r => createWatcher(r, ctx, publicThis, key));4382 }4383 else {4384 watch(getter, raw.handler.bind(publicThis), raw);4385 }4386 }4387 else {4388 warn(`Invalid watch option: "${key}"`);4389 }4390}4391function resolveMergedOptions(instance) {4392 const raw = instance.type;4393 const { __merged, mixins, extends: extendsOptions } = raw;4394 if (__merged)4395 return __merged;4396 const globalMixins = instance.appContext.mixins;4397 if (!globalMixins.length && !mixins && !extendsOptions)4398 return raw;4399 const options = {};4400 globalMixins.forEach(m => mergeOptions(options, m, instance));4401 extendsOptions && mergeOptions(options, extendsOptions, instance);4402 mixins && mixins.forEach(m => mergeOptions(options, m, instance));4403 mergeOptions(options, raw, instance);4404 return (raw.__merged = options);4405}4406function mergeOptions(to, from, instance) {4407 const strats = instance.appContext.config.optionMergeStrategies;4408 for (const key in from) {4409 const strat = strats && strats[key];4410 if (strat) {4411 to[key] = strat(to[key], from[key], instance.proxy, key);4412 }4413 else if (!hasOwn(to, key)) {4414 to[key] = from[key];4415 }4416 }4417}4418const publicPropertiesMap = {4419 $: i => i,4420 $el: i => i.vnode.el,4421 $data: i => i.data,4422 $props: i => ( shallowReadonly(i.props) ),4423 $attrs: i => ( shallowReadonly(i.attrs) ),4424 $slots: i => ( shallowReadonly(i.slots) ),4425 $refs: i => ( shallowReadonly(i.refs) ),4426 $parent: i => i.parent && i.parent.proxy,4427 $root: i => i.root && i.root.proxy,4428 $emit: i => i.emit,4429 $options: i => ( resolveMergedOptions(i) ),4430 $forceUpdate: i => () => queueJob(i.update),4431 $nextTick: () => nextTick,4432 $watch: i => instanceWatch.bind(i) 4433};4434const PublicInstanceProxyHandlers = {4435 get({ _: instance }, key) {4436 const { ctx, setupState, data, props, accessCache, type, appContext } = instance;4437 // let @vue/reatvitiy know it should never observe Vue public instances.4438 if (key === "__v_skip" /* skip */) {4439 return true;4440 }4441 // data / props / ctx4442 // This getter gets called for every property access on the render context4443 // during render and is a major hotspot. The most expensive part of this4444 // is the multiple hasOwn() calls. It's much faster to do a simple property4445 // access on a plain object, so we use an accessCache object (with null4446 // prototype) to memoize what access type a key corresponds to.4447 if (key[0] !== '$') {4448 const n = accessCache[key];4449 if (n !== undefined) {4450 switch (n) {4451 case 0 /* SETUP */:4452 return setupState[key];4453 case 1 /* DATA */:4454 return data[key];4455 case 3 /* CONTEXT */:4456 return ctx[key];4457 case 2 /* PROPS */:4458 return props[key];4459 // default: just fallthrough4460 }4461 }4462 else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {4463 accessCache[key] = 0 /* SETUP */;4464 return setupState[key];4465 }4466 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {4467 accessCache[key] = 1 /* DATA */;4468 return data[key];4469 }4470 else if (4471 // only cache other properties when instance has declared (thus stable)4472 // props4473 type.props &&4474 hasOwn(normalizePropsOptions(type.props)[0], key)) {4475 accessCache[key] = 2 /* PROPS */;4476 return props[key];4477 }4478 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {4479 accessCache[key] = 3 /* CONTEXT */;4480 return ctx[key];4481 }4482 else {4483 accessCache[key] = 4 /* OTHER */;4484 }4485 }4486 const publicGetter = publicPropertiesMap[key];4487 let cssModule, globalProperties;4488 // public $xxx properties4489 if (publicGetter) {4490 if ( key === '$attrs') {4491 markAttrsAccessed();4492 }4493 return publicGetter(instance);4494 }4495 else if (4496 // css module (injected by vue-loader)4497 (cssModule = type.__cssModules) &&4498 (cssModule = cssModule[key])) {4499 return cssModule;4500 }4501 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {4502 // user may set custom properties to `this` that start with `$`4503 accessCache[key] = 3 /* CONTEXT */;4504 return ctx[key];4505 }4506 else if (4507 // global properties4508 ((globalProperties = appContext.config.globalProperties),4509 hasOwn(globalProperties, key))) {4510 return globalProperties[key];4511 }4512 else if (4513 currentRenderingInstance &&4514 // #1091 avoid internal isRef/isVNode checks on component instance leading4515 // to infinite warning loop4516 key.indexOf('__v') !== 0) {4517 if (data !== EMPTY_OBJ && key[0] === '$' && hasOwn(data, key)) {4518 warn(`Property ${JSON.stringify(key)} must be accessed via $data because it starts with a reserved ` +4519 `character and is not proxied on the render context.`);4520 }4521 else {4522 warn(`Property ${JSON.stringify(key)} was accessed during render ` +4523 `but is not defined on instance.`);4524 }4525 }4526 },4527 set({ _: instance }, key, value) {4528 const { data, setupState, ctx } = instance;4529 if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {4530 setupState[key] = value;4531 }4532 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {4533 data[key] = value;4534 }4535 else if (key in instance.props) {4536 4537 warn(`Attempting to mutate prop "${key}". Props are readonly.`, instance);4538 return false;4539 }4540 if (key[0] === '$' && key.slice(1) in instance) {4541 4542 warn(`Attempting to mutate public property "${key}". ` +4543 `Properties starting with $ are reserved and readonly.`, instance);4544 return false;4545 }4546 else {4547 if ( key in instance.appContext.config.globalProperties) {4548 Object.defineProperty(ctx, key, {4549 enumerable: true,4550 configurable: true,4551 value4552 });4553 }4554 else {4555 ctx[key] = value;4556 }4557 }4558 return true;4559 },4560 has({ _: { data, setupState, accessCache, ctx, type, appContext } }, key) {4561 return (accessCache[key] !== undefined ||4562 (data !== EMPTY_OBJ && hasOwn(data, key)) ||4563 (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||4564 (type.props && hasOwn(normalizePropsOptions(type.props)[0], key)) ||4565 hasOwn(ctx, key) ||4566 hasOwn(publicPropertiesMap, key) ||4567 hasOwn(appContext.config.globalProperties, key));4568 }4569};4570{4571 PublicInstanceProxyHandlers.ownKeys = (target) => {4572 warn(`Avoid app logic that relies on enumerating keys on a component instance. ` +4573 `The keys will be empty in production mode to avoid performance overhead.`);4574 return Reflect.ownKeys(target);4575 };4576}4577const RuntimeCompiledPublicInstanceProxyHandlers = {4578 ...PublicInstanceProxyHandlers,4579 get(target, key) {4580 // fast path for unscopables when using `with` block4581 if (key === Symbol.unscopables) {4582 return;4583 }4584 return PublicInstanceProxyHandlers.get(target, key, target);4585 },4586 has(_, key) {4587 const has = key[0] !== '_' && !isGloballyWhitelisted(key);4588 if ( !has && PublicInstanceProxyHandlers.has(_, key)) {4589 warn(`Property ${JSON.stringify(key)} should not start with _ which is a reserved prefix for Vue internals.`);4590 }4591 return has;4592 }4593};4594// In dev mode, the proxy target exposes the same properties as seen on `this`4595// for easier console inspection. In prod mode it will be an empty object so4596// these properties definitions can be skipped.4597function createRenderContext(instance) {4598 const target = {};4599 // expose internal instance for proxy handlers4600 Object.defineProperty(target, `_`, {4601 configurable: true,4602 enumerable: false,4603 get: () => instance4604 });4605 // expose public properties4606 Object.keys(publicPropertiesMap).forEach(key => {4607 Object.defineProperty(target, key, {4608 configurable: true,4609 enumerable: false,4610 get: () => publicPropertiesMap[key](instance),4611 // intercepted by the proxy so no need for implementation,4612 // but needed to prevent set errors4613 set: NOOP4614 });4615 });4616 // expose global properties4617 const { globalProperties } = instance.appContext.config;4618 Object.keys(globalProperties).forEach(key => {4619 Object.defineProperty(target, key, {4620 configurable: true,4621 enumerable: false,4622 get: () => globalProperties[key],4623 set: NOOP4624 });4625 });4626 return target;4627}4628// dev only4629function exposePropsOnRenderContext(instance) {4630 const { ctx, type: { props: propsOptions } } = instance;4631 if (propsOptions) {4632 Object.keys(normalizePropsOptions(propsOptions)[0]).forEach(key => {4633 Object.defineProperty(ctx, key, {4634 enumerable: true,4635 configurable: true,4636 get: () => instance.props[key],4637 set: NOOP4638 });4639 });4640 }4641}4642// dev only4643function exposeSetupStateOnRenderContext(instance) {4644 const { ctx, setupState } = instance;4645 Object.keys(toRaw(setupState)).forEach(key => {4646 Object.defineProperty(ctx, key, { ...

Full Screen

Full Screen

setup.js

Source:setup.js Github

copy

Full Screen

...178 return data[key]179 }180 else if (181 type.props &&182 hasOwn(normalizePropsOptions(type.props)[0], key)) {183 accessCache[key] = 2184 // 从 props 中取数据185 return props[key]186 }187 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {188 accessCache[key] = 3189 // 从 ctx 中取数据190 return ctx[key]191 }192 else {193 // 都取不到194 accessCache[key] = 4195 }196 }197 const publicGetter = publicPropertiesMap[key]198 let cssModule, globalProperties199 // 公开的 $xxx 属性或方法200 if (publicGetter) {201 return publicGetter(instance)202 }203 else if (204 // css 模块,通过 vue-loader 编译的时候注入205 (cssModule = type.__cssModules) &&206 (cssModule = cssModule[key])) {207 return cssModule208 }209 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {210 // 用户自定义的属性,也用 `$` 开头211 accessCache[key] = 3212 return ctx[key]213 }214 else if (215 // 全局定义的属性216 ((globalProperties = appContext.config.globalProperties),217 hasOwn(globalProperties, key))) {218 return globalProperties[key]219 }220 else if ((process.env.NODE_ENV !== 'production') &&221 currentRenderingInstance && key.indexOf('__v') !== 0) {222 if (data !== EMPTY_OBJ && key[0] === '$' && hasOwn(data, key)) {223 // 如果在 data 中定义的数据以 $ 开头,会报警告,因为 $ 是保留字符,不会做代理224 warn(`Property ${JSON.stringify(key)} must be accessed via $data because it starts with a reserved ` +225 `character and is not proxied on the render context.`)226 }227 else {228 // 在模板中使用的变量如果没有定义,报警告229 warn(`Property ${JSON.stringify(key)} was accessed during render ` +230 `but is not defined on instance.`)231 }232 }233 }234}235const PublicInstanceProxyHandlers = {236 set ({ _: instance }, key, value) {237 const { data, setupState, ctx } = instance238 if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {239 // 给 setupState 赋值240 setupState[key] = value241 }242 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {243 // 给 data 赋值244 data[key] = value245 }246 else if (key in instance.props) {247 // 不能直接给 props 赋值248 (process.env.NODE_ENV !== 'production') &&249 warn(`Attempting to mutate prop "${key}". Props are readonly.`, instance)250 return false251 }252 if (key[0] === '$' && key.slice(1) in instance) {253 // 不能给 Vue 内部以 $ 开头的保留属性赋值254 (process.env.NODE_ENV !== 'production') &&255 warn(`Attempting to mutate public property "${key}". ` +256 `Properties starting with $ are reserved and readonly.`, instance)257 return false258 }259 else {260 // 用户自定义数据赋值261 ctx[key] = value262 }263 return true264 }265}266const PublicInstanceProxyHandlers = {267 has268 ({ _: { data, setupState, accessCache, ctx, type, appContext } }, key) {269 // 依次判断270 return (accessCache[key] !== undefined ||271 (data !== EMPTY_OBJ && hasOwn(data, key)) ||272 (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||273 (type.props && hasOwn(normalizePropsOptions(type.props)[0], key)) ||274 hasOwn(ctx, key) ||275 hasOwn(publicPropertiesMap, key) ||276 hasOwn(appContext.config.globalProperties, key))277 }278}279// 判断处理 setup 函数280const { setup } = Component281if (setup) {282 // 如果 setup 函数带参数,则创建一个 setupContext283 const setupContext = (instance.setupContext =284 setup.length > 1 ? createSetupContext(instance) : null)285 // 执行 setup 函数获取结果286 const setupResult = callWithErrorHandling(setup, instance, 0 /* SETUP_FUNCTION */, [instance.props, setupContext])287 // 处理 setup 执行结果...

Full Screen

Full Screen

component.js

Source:component.js Github

copy

Full Screen

...81 // 渲染缓存82 renderCache: [],83 components: null,84 directives: null,85 propsOptions: normalizePropsOptions(type, appContext),86 emitsOptions: normalizeEmitsOptions(type, appContext),87 // 派发事件方法88 emit: null,89 emitted: null,90 propsDefaults: EMPTY_OBJ,91 inheritAttrs: type.inheritAttrs,92 // 渲染上下文 content 对象93 ctx: EMPTY_OBJ,94 data: EMPTY_OBJ,95 props: EMPTY_OBJ,96 attrs: EMPTY_OBJ,97 slots: EMPTY_OBJ,98 refs: EMPTY_OBJ,99 // setup 返回值...

Full Screen

Full Screen

componentProps.js

Source:componentProps.js Github

copy

Full Screen

...41 instance.attrs = attrs42}43function setFullProps(instance, rawProps, props, attrs) {44 // 标准化 props 的配置45 const [options, needCastKeys] = normalizePropsOptions(instance.type)46 if (rawProps) {47 for (const key in rawProps) {48 const value = rawProps[key]49 // 一些保留的 prop 比如 ref、key 是不会传递的50 if (isReservedProp(key)) {51 continue52 }53 // 连字符形式的 props 也转成驼峰形式54 let camelKey55 if (options && hasOwn(options, (camelKey = camelize(key)))) {56 props[camelKey] = value57 }58 else if (!isEmitListener(instance.type, key)) {59 // 非事件派发相关的,且不在 props 中定义的普通属性用 attrs 保留60 attrs[key] = value61 }62 }63 }64 // 遍历 props 数据求值65 if (needCastKeys) {66 // 需要做转换的 props67 const rawCurrentProps = toRaw(props)68 for (let i = 0; i < needCastKeys.length; i++) {69 const key = needCastKeys[i]70 props[key] = resolvePropValue(options, rawCurrentProps, key, rawCurrentProps[key])71 }72 }73}74function resolvePropValue(options, props, key, value) {75 const opt = options[key]76 if (opt != null) {77 const hasDefault = hasOwn(opt, 'default')78 // 默认值处理79 if (hasDefault && value === undefined) {80 const defaultValue = opt.default81 value =82 opt.type !== Function && isFunction(defaultValue)83 ? defaultValue()84 : defaultValue85 }86 // 布尔类型转换87 if (opt[0 /* shouldCast */]) {88 if (!hasOwn(props, key) && !hasDefault) {89 value = false90 }91 else if (opt[1 /* shouldCastTrue */] &&92 (value === '' || value === hyphenate(key))) {93 value = true94 }95 }96 }97 return value98}99function validateProps(props, comp) {100 const rawValues = toRaw(props)101 const options = normalizePropsOptions(comp)[0]102 for (const key in options) {103 let opt = options[key]104 if (opt == null)105 continue106 validateProp(key, rawValues[key], opt, !hasOwn(rawValues, key))107 }108}109function validateProp(name, value, prop, isAbsent) {110 const { type, required, validator } = prop111 // 检测 required112 if (required && isAbsent) {113 warn('Missing required prop: "' + name + '"')114 return115 }116 // 虽然没有值但也没有配置 required,直接返回117 if (value == null && !prop.required) {118 return119 }120 // 类型检测121 if (type != null && type !== true) {122 let isValid = false123 const types = isArray(type) ? type : [type]124 const expectedTypes = []125 // 只要指定的类型之一匹配,值就有效126 for (let i = 0; i < types.length && !isValid; i++) {127 const { valid, expectedType } = assertType(value, types[i])128 expectedTypes.push(expectedType || '')129 isValid = valid130 }131 if (!isValid) {132 warn(getInvalidTypeMessage(name, value, expectedTypes))133 return134 }135 }136 // 自定义校验器137 if (validator && !validator(value)) {138 warn('Invalid prop: custom validator check failed for prop "' + name + '".')139 }140}141function normalizePropsOptions(comp) {142 // comp.__props 用于缓存标准化的结果,有缓存,则直接返回143 if (comp.__props) {144 return comp.__props145 }146 const raw = comp.props147 const normalized = {}148 const needCastKeys = []149 // 处理 mixins 和 extends 这些 props150 let hasExtends = false151 if (!shared.isFunction(comp)) {152 const extendProps = (raw) => {153 const [props, keys] = normalizePropsOptions(raw)154 shared.extend(normalized, props)155 if (keys)156 needCastKeys.push(...keys)157 }158 if (comp.extends) {159 hasExtends = true160 extendProps(comp.extends)161 }162 if (comp.mixins) {163 hasExtends = true164 comp.mixins.forEach(extendProps)165 }166 }167 if (!raw && !hasExtends) {...

Full Screen

Full Screen

reactive.js

Source:reactive.js Github

copy

Full Screen

...62}63function updateProps(instance, rawProps, rawPrevProps, optimized) {64 const { props, attrs, vnode: { patchFlag } } = instance65 const rawCurrentProps = toRaw(props)66 const [options] = normalizePropsOptions(instance.type)67 if ((optimized || patchFlag > 0) && !(patchFlag & 16 /* FULL_PROPS */)) {68 if (patchFlag & 8 /* PROPS */) {69 // 只更新动态 props 节点70 const propsToUpdate = instance.vnode.dynamicProps71 for (let i = 0; i < propsToUpdate.length; i++) {72 const key = propsToUpdate[i]73 const value = rawProps[key]74 if (options) {75 if (hasOwn(attrs, key)) {76 attrs[key] = value77 }78 else {79 const camelizedKey = camelize(key)80 props[camelizedKey] = resolvePropValue(options, rawCurrentProps, camelizedKey, value)...

Full Screen

Full Screen

listed.js

Source:listed.js Github

copy

Full Screen

...74 // local resovled assets75 components: null,76 directives: null,77 // resolved props and emits options78 propsOptions: normalizePropsOptions(type, appContext),79 emitsOptions: normalizeEmitsOptions(type, appContext),80 // emit81 emit: null,82 emitted: null,83 // props default value84 propsDefaults: EMPTY_OBJ,85 // inheritAttrs86 inheritAttrs: type.inheritAttrs,87 // state88 ctx: EMPTY_OBJ,89 data: EMPTY_OBJ,90 props: EMPTY_OBJ,91 attrs: EMPTY_OBJ,92 slots: EMPTY_OBJ,...

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

...52 return data[key]53 }54 else if (55 type.props &&56 hasOwn(normalizePropsOptions(type.props)[0], key)) {57 accessCache[key] = 258 // 从 props 中取数据59 return props[key]60 }61 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {62 accessCache[key] = 363 // 从 ctx 中取数据64 return ctx[key]65 }66 else {67 // 都取不到68 accessCache[key] = 469 }70 }...

Full Screen

Full Screen

emit.js

Source:emit.js Github

copy

Full Screen

...48const instance = {49 uid: uid$2++,50 // ...51 // resolved props and emits options52 propsOptions: normalizePropsOptions(type, appContext),53 emitsOptions: normalizeEmitsOptions(type, appContext)54 // ...55}56function normalizeEmitsOptions(comp, appContext, asMixin = false) {57 const appId = appContext.app ? appContext.app._uid : -1;58 const cache = comp.__emits || (comp.__emits = {});59 const cached = cache[appId];60 if (cached !== undefined) {61 return cached;62 }63 const raw = comp.emits;64 let normalized = {};65 // apply mixin/extends props66 let hasExtends = false;...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');2const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');3const options = {4};5const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');6const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');7const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');2const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');3const options = {4};5const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');6const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');7const { normalizePropsOptions } = require('playwright/lib/server/common/normalizeTypes');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/server/supplements/utils/serializers');2const { ElementHandle } = require('playwright/lib/server/dom');3const { ElementHandleChannel } = require('playwright/lib/server/channels');4const { Page } = require('playwright/lib/server/page');5const { PageChannel } = require('playwright/lib/server/channels');6const { Frame } = require('playwright/lib/server/frames');7const { FrameChannel } = require('playwright/lib/server/channels');8const { BrowserContext } = require('playwright/lib/server/browserContext');9const { BrowserContextChannel } = require('playwright/lib/server/channels');10const { Browser } = require('playwright/lib/server/browser');11const { BrowserChannel } = require('playwright/lib/server/channels');12const browser = await playwright.chromium.launch();13const context = await browser.newContext();14const page = await context.newPage();15const frame = page.mainFrame();16const element = await frame.$('div');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { test } = require('@playwright/test');2const { expect } = require('@playwright/test');3test.describe('normalizePropsOptions', () => {4 test('should work with default values', async ({}) => {5 const result = normalizePropsOptions({});6 expect(result).toEqual({7 });8 });9 test('should work with custom values', async ({}) => {10 const result = normalizePropsOptions({11 });12 expect(result).to qual({13 });14 });15});

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/server/frames');2const { getTestState } = require('../utils');3module.e ports = async function (testInfo) {4 const { page } = getTestState(testInfo);5 await page.evaluate(6 (normalizePropsOptions) => {7 const options = { a: 1, b: 2, c: 3 };8 const normalizedOptions = norm lizePropsOptions(options);9 console.log(nor alizedO-tions);10 },11};12const jsHandle = await page.evaluateHandle(() => window);13const normalizedJsHandle = normalizePropsOptions(jsHandle, {isJSHandle: true});14console.log(normalizedJsHandle);

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('@playwright/test/lib/utils');2const { test } = require('@playwright/test');3const { expect } = require('@playwright/test');4test.describe('normalizePropsOptions', () => {5 test('should work with default values', async ({}) => {6 const result = normalizePropsOptions({});7 expect(result).toEqual({8 });9 });10 test('should work with custom values', async ({}) => {11 const result = normalizePropsOptions({12 });13 expect(result).toEqual({14 });15 });16});

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/server/frames');2const { getTestState } = require('../utils');3module.exports = async function (testInfo) {4 const { page } = getTestState(testInfo);5 await page.evaluate(6 (normalizePropsOptions) => {7 const options = { a: 1, b: 2, c: 3 };8 const normalizedOptions = normalizePropsOptions(options);9 console.log(normalizedOptions);10 },11 );12};

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/utils/normalizeTypes');2const options = {3 da{dPageo} = equire(ts,ay r est/lib/sver/pg)======4{ BowsrCtext} qure'laywrigh/lb/erver/br/wo rC etixr'ptions method of Playwright Internal5st { normalizePropsOptions } = require('playwright/lib/utils/normalizeTypes');6co stxt t=ewPge({}, nu,ull,nll, ull);7conCx =Cntt({}ull, ul );8nrmalizpsOpio(pg,{9});10n',malizPopOptios(rowsCox,{11}); ariaValueText: 'aria-value-text',

Full Screen

Using AI Code Generation

copy

Full Screen

1cns{nrmzPrpsOpin}=rqr('c 'css',/li/vr/mjs');2};3const normalizedProps = stimalizdtnopsOptions(ps:ps);4console.log(no malizedProp');5t { normatizP',6 placehrlder:p'tOsons } = require('playwright/lib/server/frames');7t roltio'test',s = {8} height: 200,9};10Thiz`edOptioneSelscair`PropsOptions(options);lAPI.log(normasth v s`t`r. Itns te l bjcwth th folon ppis:11- `parsed` - parsed selerto. objoct.ule.exports = {12 iecoor =noTss=Eivr {13 use: {SelecreSelcr(elecr14 viewport: { wiSelech r20, height: 1080 },15 },16 },17 {18 use: {19 viewport: { width: 1920, height

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/client/helper');2const options = {3};4const normalizedOptions = normalizePropsOptions(options);5console.log(normalizedOptions);6module.exports = {7 {8 use: {9 viewport: { width: 1920, height: 1080 },10 },11 },12 {13 use: {14 viewport: { width: 1920, height: 1080 },15 },16 },17 {18 use: {19 viewport: { width: 1920, height

Full Screen

Using AI Code Generation

copy

Full Screen

1const { normalizePropsOptions } = require('playwright/lib/client/clientHelper');2const { Page } = require('playwright/lib/server/page');3const { BrowserContext } = require('playwright/lib/server/browserContext');4const page = new Page({}, null, null, null, null);5const browserContext = new BrowserContext({}, null, null);6normalizePropsOptions(page, {7});8normalizePropsOptions(browserContext, {9});

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful