Best JavaScript code snippet using playwright-internal
vue.runtime.esm.js
Source:vue.runtime.esm.js
...1750 [bar, this.y]1751])1752*/1753const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text');1754function validateDirectiveName(name) {1755 if (isBuiltInDirective(name)) {1756 warn('Do not use built-in directive ids as custom directive id: ' + name);1757 }1758}1759function createAppContext() {1760 return {1761 app: null,1762 config: {1763 isNativeTag: NO,1764 performance: false,1765 globalProperties: {},1766 optionMergeStrategies: {},1767 isCustomElement: NO,1768 errorHandler: undefined,1769 warnHandler: undefined1770 },1771 mixins: [],1772 components: {},1773 directives: {},1774 provides: Object.create(null)1775 };1776}1777let uid$1 = 0;1778// fixed by xxxxxx1779function createAppAPI() {1780 return function createApp(rootComponent, rootProps = null) {1781 if (rootProps != null && !isObject(rootProps)) {1782 (process.env.NODE_ENV !== 'production') && warn(`root props passed to app.mount() must be an object.`);1783 rootProps = null;1784 }1785 const context = createAppContext();1786 const installedPlugins = new Set();1787 // fixed by xxxxxx1788 // let isMounted = false1789 const app = (context.app = {1790 _uid: uid$1++,1791 _component: rootComponent,1792 _props: rootProps,1793 _container: null,1794 _context: context,1795 version,1796 get config() {1797 return context.config;1798 },1799 set config(v) {1800 if ((process.env.NODE_ENV !== 'production')) {1801 warn(`app.config cannot be replaced. Modify individual options instead.`);1802 }1803 },1804 use(plugin, ...options) {1805 if (installedPlugins.has(plugin)) {1806 (process.env.NODE_ENV !== 'production') && warn(`Plugin has already been applied to target app.`);1807 }1808 else if (plugin && isFunction(plugin.install)) {1809 installedPlugins.add(plugin);1810 plugin.install(app, ...options);1811 }1812 else if (isFunction(plugin)) {1813 installedPlugins.add(plugin);1814 plugin(app, ...options);1815 }1816 else if ((process.env.NODE_ENV !== 'production')) {1817 warn(`A plugin must either be a function or an object with an "install" ` +1818 `function.`);1819 }1820 return app;1821 },1822 mixin(mixin) {1823 if (__VUE_OPTIONS_API__) {1824 if (!context.mixins.includes(mixin)) {1825 context.mixins.push(mixin);1826 }1827 else if ((process.env.NODE_ENV !== 'production')) {1828 warn('Mixin has already been applied to target app' +1829 (mixin.name ? `: ${mixin.name}` : ''));1830 }1831 }1832 else if ((process.env.NODE_ENV !== 'production')) {1833 warn('Mixins are only available in builds supporting Options API');1834 }1835 return app;1836 },1837 component(name, component) {1838 if ((process.env.NODE_ENV !== 'production')) {1839 validateComponentName(name, context.config);1840 }1841 if (!component) {1842 return context.components[name];1843 }1844 if ((process.env.NODE_ENV !== 'production') && context.components[name]) {1845 warn(`Component "${name}" has already been registered in target app.`);1846 }1847 context.components[name] = component;1848 return app;1849 },1850 directive(name, directive) {1851 if ((process.env.NODE_ENV !== 'production')) {1852 validateDirectiveName(name);1853 }1854 if (!directive) {1855 return context.directives[name];1856 }1857 if ((process.env.NODE_ENV !== 'production') && context.directives[name]) {1858 warn(`Directive "${name}" has already been registered in target app.`);1859 }1860 context.directives[name] = directive;1861 return app;1862 },1863 // fixed by xxxxxx1864 mount() { },1865 // fixed by xxxxxx1866 unmount() { },1867 provide(key, value) {1868 if ((process.env.NODE_ENV !== 'production') && key in context.provides) {1869 warn(`App already provides property with key "${String(key)}". ` +1870 `It will be overwritten with the new value.`);1871 }1872 // TypeScript doesn't allow symbols as index type1873 // https://github.com/Microsoft/TypeScript/issues/245871874 context.provides[key] = value;1875 return app;1876 }1877 });1878 return app;1879 };1880}1881const queuePostRenderEffect = queuePostFlushCb;1882// Simple effect.1883function watchEffect(effect, options) {1884 return doWatch(effect, null, options);1885}1886// initial value for watchers to trigger on undefined initial values1887const INITIAL_WATCHER_VALUE = {};1888// implementation1889function watch(source, cb, options) {1890 if ((process.env.NODE_ENV !== 'production') && !isFunction(cb)) {1891 warn(`\`watch(fn, options?)\` signature has been moved to a separate API. ` +1892 `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +1893 `supports \`watch(source, cb, options?) signature.`);1894 }1895 return doWatch(source, cb, options);1896}1897function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ, instance = currentInstance) {1898 if ((process.env.NODE_ENV !== 'production') && !cb) {1899 if (immediate !== undefined) {1900 warn(`watch() "immediate" option is only respected when using the ` +1901 `watch(source, callback, options?) signature.`);1902 }1903 if (deep !== undefined) {1904 warn(`watch() "deep" option is only respected when using the ` +1905 `watch(source, callback, options?) signature.`);1906 }1907 }1908 const warnInvalidSource = (s) => {1909 warn(`Invalid watch source: `, s, `A watch source can only be a getter/effect function, a ref, ` +1910 `a reactive object, or an array of these types.`);1911 };1912 let getter;1913 const isRefSource = isRef(source);1914 if (isRefSource) {1915 getter = () => source.value;1916 }1917 else if (isReactive(source)) {1918 getter = () => source;1919 deep = true;1920 }1921 else if (isArray(source)) {1922 getter = () => source.map(s => {1923 if (isRef(s)) {1924 return s.value;1925 }1926 else if (isReactive(s)) {1927 return traverse(s);1928 }1929 else if (isFunction(s)) {1930 return callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */);1931 }1932 else {1933 (process.env.NODE_ENV !== 'production') && warnInvalidSource(s);1934 }1935 });1936 }1937 else if (isFunction(source)) {1938 if (cb) {1939 // getter with cb1940 getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */);1941 }1942 else {1943 // no cb -> simple effect1944 getter = () => {1945 if (instance && instance.isUnmounted) {1946 return;1947 }1948 if (cleanup) {1949 cleanup();1950 }1951 return callWithErrorHandling(source, instance, 3 /* WATCH_CALLBACK */, [onInvalidate]);1952 };1953 }1954 }1955 else {1956 getter = NOOP;1957 (process.env.NODE_ENV !== 'production') && warnInvalidSource(source);1958 }1959 if (cb && deep) {1960 const baseGetter = getter;1961 getter = () => traverse(baseGetter());1962 }1963 let cleanup;1964 const onInvalidate = (fn) => {1965 cleanup = runner.options.onStop = () => {1966 callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */);1967 };1968 };1969 let oldValue = isArray(source) ? [] : INITIAL_WATCHER_VALUE;1970 const job = () => {1971 if (!runner.active) {1972 return;1973 }1974 if (cb) {1975 // watch(source, cb)1976 const newValue = runner();1977 if (deep || isRefSource || hasChanged(newValue, oldValue)) {1978 // cleanup before running cb again1979 if (cleanup) {1980 cleanup();1981 }1982 callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [1983 newValue,1984 // pass undefined as the old value when it's changed for the first time1985 oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,1986 onInvalidate1987 ]);1988 oldValue = newValue;1989 }1990 }1991 else {1992 // watchEffect1993 runner();1994 }1995 };1996 // important: mark the job as a watcher callback so that scheduler knows it1997 // it is allowed to self-trigger (#1727)1998 job.allowRecurse = !!cb;1999 let scheduler;2000 if (flush === 'sync') {2001 scheduler = job;2002 }2003 else if (flush === 'post') {2004 scheduler = () => queuePostRenderEffect(job, instance && instance.suspense);2005 }2006 else {2007 // default: 'pre'2008 scheduler = () => {2009 if (!instance || instance.isMounted) {2010 queuePreFlushCb(job);2011 }2012 else {2013 // with 'pre' option, the first call must happen before2014 // the component is mounted so it is called synchronously.2015 job();2016 }2017 };2018 }2019 const runner = effect(getter, {2020 lazy: true,2021 onTrack,2022 onTrigger,2023 scheduler2024 });2025 recordInstanceBoundEffect(runner);2026 // initial run2027 if (cb) {2028 if (immediate) {2029 job();2030 }2031 else {2032 oldValue = runner();2033 }2034 }2035 else if (flush === 'post') {2036 queuePostRenderEffect(runner, instance && instance.suspense);2037 }2038 else {2039 runner();2040 }2041 return () => {2042 stop(runner);2043 if (instance) {2044 remove(instance.effects, runner);2045 }2046 };2047}2048// this.$watch2049function instanceWatch(source, cb, options) {2050 const publicThis = this.proxy;2051 const getter = isString(source)2052 ? () => publicThis[source]2053 : source.bind(publicThis);2054 return doWatch(getter, cb.bind(publicThis), options, this);2055}2056function traverse(value, seen = new Set()) {2057 if (!isObject(value) || seen.has(value)) {2058 return value;2059 }2060 seen.add(value);2061 if (isRef(value)) {2062 traverse(value.value, seen);2063 }2064 else if (isArray(value)) {2065 for (let i = 0; i < value.length; i++) {2066 traverse(value[i], seen);2067 }2068 }2069 else if (isMap(value)) {2070 value.forEach((_, key) => {2071 // to register mutation dep for existing keys2072 traverse(value.get(key), seen);2073 });2074 }2075 else if (isSet(value)) {2076 value.forEach(v => {2077 traverse(v, seen);2078 });2079 }2080 else {2081 for (const key in value) {2082 traverse(value[key], seen);2083 }2084 }2085 return value;2086}2087function provide(key, value) {2088 if (!currentInstance) {2089 if ((process.env.NODE_ENV !== 'production')) {2090 warn(`provide() can only be used inside setup().`);2091 }2092 }2093 else {2094 let provides = currentInstance.provides;2095 // by default an instance inherits its parent's provides object2096 // but when it needs to provide values of its own, it creates its2097 // own provides object using parent provides object as prototype.2098 // this way in `inject` we can simply look up injections from direct2099 // parent and let the prototype chain do the work.2100 const parentProvides = currentInstance.parent && currentInstance.parent.provides;2101 if (parentProvides === provides) {2102 provides = currentInstance.provides = Object.create(parentProvides);2103 }2104 // TS doesn't allow symbol as index type2105 provides[key] = value;2106 }2107}2108function inject(key, defaultValue, treatDefaultAsFactory = false) {2109 // fallback to `currentRenderingInstance` so that this can be called in2110 // a functional component2111 const instance = currentInstance || currentRenderingInstance;2112 if (instance) {2113 const provides = instance.provides;2114 if (key in provides) {2115 // TS doesn't allow symbol as index type2116 return provides[key];2117 }2118 else if (arguments.length > 1) {2119 return treatDefaultAsFactory && isFunction(defaultValue)2120 ? defaultValue()2121 : defaultValue;2122 }2123 else if ((process.env.NODE_ENV !== 'production')) {2124 warn(`injection "${String(key)}" not found.`);2125 }2126 }2127 else if ((process.env.NODE_ENV !== 'production')) {2128 warn(`inject() can only be used inside setup() or functional components.`);2129 }2130}2131function createDuplicateChecker() {2132 const cache = Object.create(null);2133 return (type, key) => {2134 if (cache[key]) {2135 warn(`${type} property "${key}" is already defined in ${cache[key]}.`);2136 }2137 else {2138 cache[key] = type;2139 }2140 };2141}2142let isInBeforeCreate = false;2143function applyOptions(instance, options, deferredData = [], deferredWatch = [], asMixin = false) {2144 const { 2145 // composition2146 mixins, extends: extendsOptions, 2147 // state2148 data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions, 2149 // assets2150 components, directives, 2151 // lifecycle2152 beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy, beforeUnmount, destroyed, unmounted, render, renderTracked, renderTriggered, errorCaptured } = options;2153 const publicThis = instance.proxy;2154 const ctx = instance.ctx;2155 const globalMixins = instance.appContext.mixins;2156 if (asMixin && render && instance.render === NOOP) {2157 instance.render = render;2158 }2159 // applyOptions is called non-as-mixin once per instance2160 if (!asMixin) {2161 isInBeforeCreate = true;2162 callSyncHook('beforeCreate', options, publicThis, globalMixins);2163 isInBeforeCreate = false;2164 // global mixins are applied first2165 applyMixins(instance, globalMixins, deferredData, deferredWatch);2166 }2167 // extending a base component...2168 if (extendsOptions) {2169 applyOptions(instance, extendsOptions, deferredData, deferredWatch, true);2170 }2171 // local mixins2172 if (mixins) {2173 applyMixins(instance, mixins, deferredData, deferredWatch);2174 }2175 const checkDuplicateProperties = (process.env.NODE_ENV !== 'production') ? createDuplicateChecker() : null;2176 if ((process.env.NODE_ENV !== 'production')) {2177 const [propsOptions] = instance.propsOptions;2178 if (propsOptions) {2179 for (const key in propsOptions) {2180 checkDuplicateProperties("Props" /* PROPS */, key);2181 }2182 }2183 }2184 // options initialization order (to be consistent with Vue 2):2185 // - props (already done outside of this function)2186 // - inject2187 // - methods2188 // - data (deferred since it relies on `this` access)2189 // - computed2190 // - watch (deferred since it relies on `this` access)2191 // fixed by xxxxxx2192 if (!__VUE_CREATED_DEFERRED__ && injectOptions) {2193 if (isArray(injectOptions)) {2194 for (let i = 0; i < injectOptions.length; i++) {2195 const key = injectOptions[i];2196 ctx[key] = inject(key);2197 if ((process.env.NODE_ENV !== 'production')) {2198 checkDuplicateProperties("Inject" /* INJECT */, key);2199 }2200 }2201 }2202 else {2203 for (const key in injectOptions) {2204 const opt = injectOptions[key];2205 if (isObject(opt)) {2206 ctx[key] = inject(opt.from || key, opt.default, true /* treat default function as factory */);2207 }2208 else {2209 ctx[key] = inject(opt);2210 }2211 if ((process.env.NODE_ENV !== 'production')) {2212 checkDuplicateProperties("Inject" /* INJECT */, key);2213 }2214 }2215 }2216 }2217 if (methods) {2218 for (const key in methods) {2219 const methodHandler = methods[key];2220 if (isFunction(methodHandler)) {2221 ctx[key] = methodHandler.bind(publicThis);2222 if ((process.env.NODE_ENV !== 'production')) {2223 checkDuplicateProperties("Methods" /* METHODS */, key);2224 }2225 }2226 else if ((process.env.NODE_ENV !== 'production')) {2227 warn(`Method "${key}" has type "${typeof methodHandler}" in the component definition. ` +2228 `Did you reference the function correctly?`);2229 }2230 }2231 }2232 if (!asMixin) {2233 if (deferredData.length) {2234 deferredData.forEach(dataFn => resolveData(instance, dataFn, publicThis));2235 }2236 if (dataOptions) {2237 resolveData(instance, dataOptions, publicThis);2238 }2239 if ((process.env.NODE_ENV !== 'production')) {2240 const rawData = toRaw(instance.data);2241 for (const key in rawData) {2242 checkDuplicateProperties("Data" /* DATA */, key);2243 // expose data on ctx during dev2244 if (key[0] !== '$' && key[0] !== '_') {2245 Object.defineProperty(ctx, key, {2246 configurable: true,2247 enumerable: true,2248 get: () => rawData[key],2249 set: NOOP2250 });2251 }2252 }2253 }2254 }2255 else if (dataOptions) {2256 deferredData.push(dataOptions);2257 }2258 if (computedOptions) {2259 for (const key in computedOptions) {2260 const opt = computedOptions[key];2261 const get = isFunction(opt)2262 ? opt.bind(publicThis, publicThis)2263 : isFunction(opt.get)2264 ? opt.get.bind(publicThis, publicThis)2265 : NOOP;2266 if ((process.env.NODE_ENV !== 'production') && get === NOOP) {2267 warn(`Computed property "${key}" has no getter.`);2268 }2269 const set = !isFunction(opt) && isFunction(opt.set)2270 ? opt.set.bind(publicThis)2271 : (process.env.NODE_ENV !== 'production')2272 ? () => {2273 warn(`Write operation failed: computed property "${key}" is readonly.`);2274 }2275 : NOOP;2276 const c = computed$1({2277 get,2278 set2279 });2280 Object.defineProperty(ctx, key, {2281 enumerable: true,2282 configurable: true,2283 get: () => c.value,2284 set: v => (c.value = v)2285 });2286 if ((process.env.NODE_ENV !== 'production')) {2287 checkDuplicateProperties("Computed" /* COMPUTED */, key);2288 }2289 }2290 }2291 if (watchOptions) {2292 deferredWatch.push(watchOptions);2293 }2294 if (!asMixin && deferredWatch.length) {2295 deferredWatch.forEach(watchOptions => {2296 for (const key in watchOptions) {2297 createWatcher(watchOptions[key], ctx, publicThis, key);2298 }2299 });2300 }2301 // fixed by xxxxxx2302 if (!__VUE_CREATED_DEFERRED__ && provideOptions) {2303 const provides = isFunction(provideOptions)2304 ? provideOptions.call(publicThis)2305 : provideOptions;2306 for (const key in provides) {2307 provide(key, provides[key]);2308 }2309 }2310 // asset options.2311 // To reduce memory usage, only components with mixins or extends will have2312 // resolved asset registry attached to instance.2313 if (asMixin) {2314 if (components) {2315 extend(instance.components ||2316 (instance.components = extend({}, instance.type.components)), components);2317 }2318 if (directives) {2319 extend(instance.directives ||2320 (instance.directives = extend({}, instance.type.directives)), directives);2321 }2322 }2323 // fixed by xxxxxx2324 // lifecycle options2325 if (__VUE_CREATED_DEFERRED__) {2326 ctx.$callSyncHook = function (name) {2327 return callSyncHook(name, options, publicThis, globalMixins);2328 };2329 }2330 else if (!asMixin) {2331 callSyncHook('created', options, publicThis, globalMixins);2332 }2333 if (beforeMount) {2334 onBeforeMount(beforeMount.bind(publicThis));2335 }2336 if (mounted) {2337 onMounted(mounted.bind(publicThis));2338 }2339 if (beforeUpdate) {2340 onBeforeUpdate(beforeUpdate.bind(publicThis));2341 }2342 if (updated) {2343 onUpdated(updated.bind(publicThis));2344 }2345 if (activated) {2346 onActivated(activated.bind(publicThis));2347 }2348 if (deactivated) {2349 onDeactivated(deactivated.bind(publicThis));2350 }2351 if (errorCaptured) {2352 onErrorCaptured(errorCaptured.bind(publicThis));2353 }2354 if (renderTracked) {2355 onRenderTracked(renderTracked.bind(publicThis));2356 }2357 if (renderTriggered) {2358 onRenderTriggered(renderTriggered.bind(publicThis));2359 }2360 if ((process.env.NODE_ENV !== 'production') && beforeDestroy) {2361 warn(`\`beforeDestroy\` has been renamed to \`beforeUnmount\`.`);2362 }2363 if (beforeUnmount) {2364 onBeforeUnmount(beforeUnmount.bind(publicThis));2365 }2366 if ((process.env.NODE_ENV !== 'production') && destroyed) {2367 warn(`\`destroyed\` has been renamed to \`unmounted\`.`);2368 }2369 if (unmounted) {2370 onUnmounted(unmounted.bind(publicThis));2371 }2372 // fixed by xxxxxx2373 if (instance.ctx.$onApplyOptions) {2374 instance.ctx.$onApplyOptions(options, instance, publicThis);2375 }2376}2377function callSyncHook(name, options, ctx, globalMixins) {2378 callHookFromMixins(name, globalMixins, ctx);2379 const { extends: base, mixins } = options;2380 if (base) {2381 callHookFromExtends(name, base, ctx);2382 }2383 if (mixins) {2384 callHookFromMixins(name, mixins, ctx);2385 }2386 const selfHook = options[name];2387 if (selfHook) {2388 selfHook.call(ctx);2389 }2390}2391function callHookFromExtends(name, base, ctx) {2392 if (base.extends) {2393 callHookFromExtends(name, base.extends, ctx);2394 }2395 const baseHook = base[name];2396 if (baseHook) {2397 baseHook.call(ctx);2398 }2399}2400function callHookFromMixins(name, mixins, ctx) {2401 for (let i = 0; i < mixins.length; i++) {2402 const chainedMixins = mixins[i].mixins;2403 if (chainedMixins) {2404 callHookFromMixins(name, chainedMixins, ctx);2405 }2406 const fn = mixins[i][name];2407 if (fn) {2408 fn.call(ctx);2409 }2410 }2411}2412function applyMixins(instance, mixins, deferredData, deferredWatch) {2413 for (let i = 0; i < mixins.length; i++) {2414 applyOptions(instance, mixins[i], deferredData, deferredWatch, true);2415 }2416}2417function resolveData(instance, dataFn, publicThis) {2418 if ((process.env.NODE_ENV !== 'production') && !isFunction(dataFn)) {2419 warn(`The data option must be a function. ` +2420 `Plain object usage is no longer supported.`);2421 }2422 const data = dataFn.call(publicThis, publicThis);2423 if ((process.env.NODE_ENV !== 'production') && isPromise(data)) {2424 warn(`data() returned a Promise - note data() cannot be async; If you ` +2425 `intend to perform data fetching before component renders, use ` +2426 `async setup() + <Suspense>.`);2427 }2428 if (!isObject(data)) {2429 (process.env.NODE_ENV !== 'production') && warn(`data() should return an object.`);2430 }2431 else if (instance.data === EMPTY_OBJ) {2432 instance.data = reactive(data);2433 }2434 else {2435 // existing data: this is a mixin or extends.2436 extend(instance.data, data);2437 }2438}2439function createWatcher(raw, ctx, publicThis, key) {2440 const getter = key.includes('.')2441 ? createPathGetter(publicThis, key)2442 : () => publicThis[key];2443 if (isString(raw)) {2444 const handler = ctx[raw];2445 if (isFunction(handler)) {2446 watch(getter, handler);2447 }2448 else if ((process.env.NODE_ENV !== 'production')) {2449 warn(`Invalid watch handler specified by key "${raw}"`, handler);2450 }2451 }2452 else if (isFunction(raw)) {2453 watch(getter, raw.bind(publicThis));2454 }2455 else if (isObject(raw)) {2456 if (isArray(raw)) {2457 raw.forEach(r => createWatcher(r, ctx, publicThis, key));2458 }2459 else {2460 const handler = isFunction(raw.handler)2461 ? raw.handler.bind(publicThis)2462 : ctx[raw.handler];2463 if (isFunction(handler)) {2464 watch(getter, handler, raw);2465 }2466 else if ((process.env.NODE_ENV !== 'production')) {2467 warn(`Invalid watch handler specified by key "${raw.handler}"`, handler);2468 }2469 }2470 }2471 else if ((process.env.NODE_ENV !== 'production')) {2472 warn(`Invalid watch option: "${key}"`, raw);2473 }2474}2475function createPathGetter(ctx, path) {2476 const segments = path.split('.');2477 return () => {2478 let cur = ctx;2479 for (let i = 0; i < segments.length && cur; i++) {2480 cur = cur[segments[i]];2481 }2482 return cur;2483 };2484}2485function resolveMergedOptions(instance) {2486 const raw = instance.type;2487 const { __merged, mixins, extends: extendsOptions } = raw;2488 if (__merged)2489 return __merged;2490 const globalMixins = instance.appContext.mixins;2491 if (!globalMixins.length && !mixins && !extendsOptions)2492 return raw;2493 const options = {};2494 globalMixins.forEach(m => mergeOptions(options, m, instance));2495 mergeOptions(options, raw, instance);2496 return (raw.__merged = options);2497}2498function mergeOptions(to, from, instance) {2499 const strats = instance.appContext.config.optionMergeStrategies;2500 const { mixins, extends: extendsOptions } = from;2501 extendsOptions && mergeOptions(to, extendsOptions, instance);2502 mixins &&2503 mixins.forEach((m) => mergeOptions(to, m, instance));2504 for (const key in from) {2505 if (strats && hasOwn(strats, key)) {2506 to[key] = strats[key](to[key], from[key], instance.proxy, key);2507 }2508 else {2509 to[key] = from[key];2510 }2511 }2512}2513const publicPropertiesMap = extend(Object.create(null), {2514 $: i => i,2515 $el: i => i.vnode.el,2516 $data: i => i.data,2517 $props: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.props) : i.props),2518 $attrs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.attrs) : i.attrs),2519 $slots: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.slots) : i.slots),2520 $refs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.refs) : i.refs),2521 $parent: i => i.parent && i.parent.proxy,2522 $root: i => i.root && i.root.proxy,2523 $emit: i => i.emit,2524 $options: i => (__VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),2525 $forceUpdate: i => () => queueJob(i.update),2526 // $nextTick: () => nextTick, // fixed by xxxxxx2527 $watch: i => (__VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP)2528});2529const PublicInstanceProxyHandlers = {2530 get({ _: instance }, key) {2531 const { ctx, setupState, data, props, accessCache, type, appContext } = instance;2532 // let @vue/reactivity know it should never observe Vue public instances.2533 if (key === "__v_skip" /* SKIP */) {2534 return true;2535 }2536 // data / props / ctx2537 // This getter gets called for every property access on the render context2538 // during render and is a major hotspot. The most expensive part of this2539 // is the multiple hasOwn() calls. It's much faster to do a simple property2540 // access on a plain object, so we use an accessCache object (with null2541 // prototype) to memoize what access type a key corresponds to.2542 let normalizedProps;2543 if (key[0] !== '$') {2544 const n = accessCache[key];2545 if (n !== undefined) {2546 switch (n) {2547 case 0 /* SETUP */:2548 return setupState[key];2549 case 1 /* DATA */:2550 return data[key];2551 case 3 /* CONTEXT */:2552 return ctx[key];2553 case 2 /* PROPS */:2554 return props[key];2555 // default: just fallthrough2556 }2557 }2558 else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {2559 accessCache[key] = 0 /* SETUP */;2560 return setupState[key];2561 }2562 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {2563 accessCache[key] = 1 /* DATA */;2564 return data[key];2565 }2566 else if (2567 // only cache other properties when instance has declared (thus stable)2568 // props2569 (normalizedProps = instance.propsOptions[0]) &&2570 hasOwn(normalizedProps, key)) {2571 accessCache[key] = 2 /* PROPS */;2572 return props[key];2573 }2574 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {2575 accessCache[key] = 3 /* CONTEXT */;2576 return ctx[key];2577 }2578 else if (!__VUE_OPTIONS_API__ || !isInBeforeCreate) {2579 accessCache[key] = 4 /* OTHER */;2580 }2581 }2582 const publicGetter = publicPropertiesMap[key];2583 let cssModule, globalProperties;2584 // public $xxx properties2585 if (publicGetter) {2586 if (key === '$attrs') {2587 track(instance, "get" /* GET */, key);2588 (process.env.NODE_ENV !== 'production') && markAttrsAccessed();2589 }2590 return publicGetter(instance);2591 }2592 else if (2593 // css module (injected by vue-loader)2594 (cssModule = type.__cssModules) &&2595 (cssModule = cssModule[key])) {2596 return cssModule;2597 }2598 else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {2599 // user may set custom properties to `this` that start with `$`2600 accessCache[key] = 3 /* CONTEXT */;2601 return ctx[key];2602 }2603 else if (2604 // global properties2605 ((globalProperties = appContext.config.globalProperties),2606 hasOwn(globalProperties, key))) {2607 return globalProperties[key];2608 }2609 else if ((process.env.NODE_ENV !== 'production') &&2610 currentRenderingInstance &&2611 (!isString(key) ||2612 // #1091 avoid internal isRef/isVNode checks on component instance leading2613 // to infinite warning loop2614 key.indexOf('__v') !== 0)) {2615 if (data !== EMPTY_OBJ &&2616 (key[0] === '$' || key[0] === '_') &&2617 hasOwn(data, key)) {2618 warn(`Property ${JSON.stringify(key)} must be accessed via $data because it starts with a reserved ` +2619 `character ("$" or "_") and is not proxied on the render context.`);2620 }2621 else {2622 warn(`Property ${JSON.stringify(key)} was accessed during render ` +2623 `but is not defined on instance.`);2624 }2625 }2626 },2627 set({ _: instance }, key, value) {2628 const { data, setupState, ctx } = instance;2629 if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {2630 setupState[key] = value;2631 }2632 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {2633 data[key] = value;2634 }2635 else if (key in instance.props) {2636 (process.env.NODE_ENV !== 'production') &&2637 warn(`Attempting to mutate prop "${key}". Props are readonly.`, instance);2638 return false;2639 }2640 if (key[0] === '$' && key.slice(1) in instance) {2641 (process.env.NODE_ENV !== 'production') &&2642 warn(`Attempting to mutate public property "${key}". ` +2643 `Properties starting with $ are reserved and readonly.`, instance);2644 return false;2645 }2646 else {2647 if ((process.env.NODE_ENV !== 'production') && key in instance.appContext.config.globalProperties) {2648 Object.defineProperty(ctx, key, {2649 enumerable: true,2650 configurable: true,2651 value2652 });2653 }2654 else {2655 ctx[key] = value;2656 }2657 }2658 return true;2659 },2660 has({ _: { data, setupState, accessCache, ctx, appContext, propsOptions } }, key) {2661 let normalizedProps;2662 return (accessCache[key] !== undefined ||2663 (data !== EMPTY_OBJ && hasOwn(data, key)) ||2664 (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||2665 ((normalizedProps = propsOptions[0]) && hasOwn(normalizedProps, key)) ||2666 hasOwn(ctx, key) ||2667 hasOwn(publicPropertiesMap, key) ||2668 hasOwn(appContext.config.globalProperties, key));2669 }2670};2671if ((process.env.NODE_ENV !== 'production') && !false) {2672 PublicInstanceProxyHandlers.ownKeys = (target) => {2673 warn(`Avoid app logic that relies on enumerating keys on a component instance. ` +2674 `The keys will be empty in production mode to avoid performance overhead.`);2675 return Reflect.ownKeys(target);2676 };2677}2678const RuntimeCompiledPublicInstanceProxyHandlers = extend({}, PublicInstanceProxyHandlers, {2679 get(target, key) {2680 // fast path for unscopables when using `with` block2681 if (key === Symbol.unscopables) {2682 return;2683 }2684 return PublicInstanceProxyHandlers.get(target, key, target);2685 },2686 has(_, key) {2687 const has = key[0] !== '_' && !isGloballyWhitelisted(key);2688 if ((process.env.NODE_ENV !== 'production') && !has && PublicInstanceProxyHandlers.has(_, key)) {2689 warn(`Property ${JSON.stringify(key)} should not start with _ which is a reserved prefix for Vue internals.`);2690 }2691 return has;2692 }2693});2694// In dev mode, the proxy target exposes the same properties as seen on `this`2695// for easier console inspection. In prod mode it will be an empty object so2696// these properties definitions can be skipped.2697function createRenderContext(instance) {2698 const target = {};2699 // expose internal instance for proxy handlers2700 Object.defineProperty(target, `_`, {2701 configurable: true,2702 enumerable: false,2703 get: () => instance2704 });2705 // expose public properties2706 Object.keys(publicPropertiesMap).forEach(key => {2707 Object.defineProperty(target, key, {2708 configurable: true,2709 enumerable: false,2710 get: () => publicPropertiesMap[key](instance),2711 // intercepted by the proxy so no need for implementation,2712 // but needed to prevent set errors2713 set: NOOP2714 });2715 });2716 // expose global properties2717 const { globalProperties } = instance.appContext.config;2718 Object.keys(globalProperties).forEach(key => {2719 Object.defineProperty(target, key, {2720 configurable: true,2721 enumerable: false,2722 get: () => globalProperties[key],2723 set: NOOP2724 });2725 });2726 return target;2727}2728// dev only2729function exposePropsOnRenderContext(instance) {2730 const { ctx, propsOptions: [propsOptions] } = instance;2731 if (propsOptions) {2732 Object.keys(propsOptions).forEach(key => {2733 Object.defineProperty(ctx, key, {2734 enumerable: true,2735 configurable: true,2736 get: () => instance.props[key],2737 set: NOOP2738 });2739 });2740 }2741}2742// dev only2743function exposeSetupStateOnRenderContext(instance) {2744 const { ctx, setupState } = instance;2745 Object.keys(toRaw(setupState)).forEach(key => {2746 if (key[0] === '$' || key[0] === '_') {2747 warn(`setup() return property ${JSON.stringify(key)} should not start with "$" or "_" ` +2748 `which are reserved prefixes for Vue internals.`);2749 return;2750 }2751 Object.defineProperty(ctx, key, {2752 enumerable: true,2753 configurable: true,2754 get: () => setupState[key],2755 set: NOOP2756 });2757 });2758}2759const emptyAppContext = createAppContext();2760let uid$2 = 0;2761function createComponentInstance(vnode, parent, suspense) {2762 const type = vnode.type;2763 // inherit parent app context - or - if root, adopt from root vnode2764 const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext;2765 const instance = {2766 uid: uid$2++,2767 vnode,2768 type,2769 parent,2770 appContext,2771 root: null,2772 next: null,2773 subTree: null,2774 update: null,2775 render: null,2776 proxy: null,2777 withProxy: null,2778 effects: null,2779 provides: parent ? parent.provides : Object.create(appContext.provides),2780 accessCache: null,2781 renderCache: [],2782 // local resovled assets2783 components: null,2784 directives: null,2785 // resolved props and emits options2786 propsOptions: normalizePropsOptions(type, appContext),2787 emitsOptions: normalizeEmitsOptions(type, appContext),2788 // emit2789 emit: null,2790 emitted: null,2791 // state2792 ctx: EMPTY_OBJ,2793 data: EMPTY_OBJ,2794 props: EMPTY_OBJ,2795 attrs: EMPTY_OBJ,2796 slots: EMPTY_OBJ,2797 refs: EMPTY_OBJ,2798 setupState: EMPTY_OBJ,2799 setupContext: null,2800 // suspense related2801 suspense,2802 suspenseId: suspense ? suspense.pendingId : 0,2803 asyncDep: null,2804 asyncResolved: false,2805 // lifecycle hooks2806 // not using enums here because it results in computed properties2807 isMounted: false,2808 isUnmounted: false,2809 isDeactivated: false,2810 bc: null,2811 c: null,2812 bm: null,2813 m: null,2814 bu: null,2815 u: null,2816 um: null,2817 bum: null,2818 da: null,2819 a: null,2820 rtg: null,2821 rtc: null,2822 ec: null2823 };2824 if ((process.env.NODE_ENV !== 'production')) {2825 instance.ctx = createRenderContext(instance);2826 }2827 else {2828 instance.ctx = { _: instance };2829 }2830 instance.root = parent ? parent.root : instance;2831 instance.emit = emit.bind(null, instance);2832 if ((process.env.NODE_ENV !== 'production') || false) ;2833 return instance;2834}2835let currentInstance = null;2836const setCurrentInstance = (instance) => {2837 currentInstance = instance;2838};2839const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component');2840function validateComponentName(name, config) {2841 const appIsNativeTag = config.isNativeTag || NO;2842 if (isBuiltInTag(name) || appIsNativeTag(name)) {2843 warn('Do not use built-in or reserved HTML elements as component id: ' + name);2844 }2845}2846let isInSSRComponentSetup = false;2847function setupComponent(instance, isSSR = false) {2848 isInSSRComponentSetup = isSSR;2849 const { props, /* children, */ shapeFlag } = instance.vnode;2850 const isStateful = shapeFlag & 4 /* STATEFUL_COMPONENT */;2851 initProps(instance, props, isStateful, isSSR);2852 // initSlots(instance, children) // fixed by xxxxxx2853 const setupResult = isStateful2854 ? setupStatefulComponent(instance, isSSR)2855 : undefined;2856 isInSSRComponentSetup = false;2857 return setupResult;2858}2859function setupStatefulComponent(instance, isSSR) {2860 const Component = instance.type;2861 if ((process.env.NODE_ENV !== 'production')) {2862 if (Component.name) {2863 validateComponentName(Component.name, instance.appContext.config);2864 }2865 if (Component.components) {2866 const names = Object.keys(Component.components);2867 for (let i = 0; i < names.length; i++) {2868 validateComponentName(names[i], instance.appContext.config);2869 }2870 }2871 if (Component.directives) {2872 const names = Object.keys(Component.directives);2873 for (let i = 0; i < names.length; i++) {2874 validateDirectiveName(names[i]);2875 }2876 }2877 }2878 // 0. create render proxy property access cache2879 instance.accessCache = {};2880 // 1. create public instance / render proxy2881 // also mark it raw so it's never observed2882 instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers);2883 if ((process.env.NODE_ENV !== 'production')) {2884 exposePropsOnRenderContext(instance);2885 }2886 // 2. call setup()2887 const { setup } = Component;2888 if (setup) {
...
runtime-core.esm-bundler.js
Source:runtime-core.esm-bundler.js
...1045])1046*/1047const valueCache = new WeakMap();1048const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text');1049function validateDirectiveName(name) {1050 if (isBuiltInDirective(name)) {1051 warn('Do not use built-in directive ids as custom directive id: ' + name);1052 }1053}1054function applyDirective(props, instance, directive, value, arg, modifiers = EMPTY_OBJ) {1055 let valueCacheForDir = valueCache.get(directive);1056 if (!valueCacheForDir) {1057 valueCacheForDir = new WeakMap();1058 valueCache.set(directive, valueCacheForDir);1059 }1060 if (isFunction(directive)) {1061 directive = {1062 mounted: directive,1063 updated: directive1064 };1065 }1066 for (const key in directive) {1067 const hook = directive[key];1068 const hookKey = `onVnode` + key[0].toUpperCase() + key.slice(1);1069 const vnodeHook = (vnode, prevVNode) => {1070 let oldValue;1071 if (prevVNode != null) {1072 oldValue = valueCacheForDir.get(prevVNode);1073 valueCacheForDir.delete(prevVNode);1074 }1075 valueCacheForDir.set(vnode, value);1076 hook(vnode.el, {1077 instance: instance.renderProxy,1078 value,1079 oldValue,1080 arg,1081 modifiers1082 }, vnode, prevVNode);1083 };1084 const existing = props[hookKey];1085 props[hookKey] = existing1086 ? [].concat(existing, vnodeHook)1087 : vnodeHook;1088 }1089}1090function withDirectives(vnode, directives) {1091 const instance = currentRenderingInstance;1092 if (instance !== null) {1093 vnode.props = vnode.props || {};1094 for (let i = 0; i < directives.length; i++) {1095 const [dir, value, arg, modifiers] = directives[i];1096 applyDirective(vnode.props, instance, dir, value, arg, modifiers);1097 }1098 }1099 else if (process.env.NODE_ENV !== 'production') {1100 warn(`withDirectives can only be used inside render functions.`);1101 }1102 return vnode;1103}1104function invokeDirectiveHook(hook, instance, vnode, prevVNode = null) {1105 callWithAsyncErrorHandling(hook, instance, 7 /* DIRECTIVE_HOOK */, [1106 vnode,1107 prevVNode1108 ]);1109}1110function createAppContext() {1111 return {1112 config: {1113 devtools: true,1114 performance: false,1115 isNativeTag: NO,1116 isCustomElement: NO,1117 errorHandler: undefined,1118 warnHandler: undefined1119 },1120 mixins: [],1121 components: {},1122 directives: {},1123 provides: {}1124 };1125}1126function createAppAPI(render) {1127 return function createApp() {1128 const context = createAppContext();1129 let isMounted = false;1130 const app = {1131 get config() {1132 return context.config;1133 },1134 set config(v) {1135 if (process.env.NODE_ENV !== 'production') {1136 warn(`app.config cannot be replaced. Modify individual options instead.`);1137 }1138 },1139 use(plugin) {1140 if (isFunction(plugin)) {1141 plugin(app);1142 }1143 else if (isFunction(plugin.install)) {1144 plugin.install(app);1145 }1146 else if (process.env.NODE_ENV !== 'production') {1147 warn(`A plugin must either be a function or an object with an "install" ` +1148 `function.`);1149 }1150 return app;1151 },1152 mixin(mixin) {1153 context.mixins.push(mixin);1154 return app;1155 },1156 component(name, component) {1157 if (process.env.NODE_ENV !== 'production') {1158 validateComponentName(name, context.config);1159 }1160 if (!component) {1161 return context.components[name];1162 }1163 else {1164 context.components[name] = component;1165 return app;1166 }1167 },1168 directive(name, directive) {1169 if (process.env.NODE_ENV !== 'production') {1170 validateDirectiveName(name);1171 }1172 if (!directive) {1173 return context.directives[name];1174 }1175 else {1176 context.directives[name] = directive;1177 return app;1178 }1179 },1180 mount(rootComponent, rootContainer, rootProps) {1181 if (!isMounted) {1182 const vnode = createVNode(rootComponent, rootProps);1183 // store app context on the root VNode.1184 // this will be set on the root instance on initial mount.1185 vnode.appContext = context;1186 render(vnode, rootContainer);1187 isMounted = true;1188 return vnode.component.renderProxy;1189 }1190 else if (process.env.NODE_ENV !== 'production') {1191 warn(`App has already been mounted. Create a new app instance instead.`);1192 }1193 },1194 provide(key, value) {1195 if (process.env.NODE_ENV !== 'production' && key in context.provides) {1196 warn(`App already provides property with key "${key}". ` +1197 `It will be overwritten with the new value.`);1198 }1199 // TypeScript doesn't allow symbols as index type1200 // https://github.com/Microsoft/TypeScript/issues/245871201 context.provides[key] = value;1202 }1203 };1204 return app;1205 };1206}1207const SuspenseSymbol = process.env.NODE_ENV !== 'production' ? Symbol('Suspense key') : Symbol();1208function createSuspenseBoundary(vnode, parent, parentComponent, container, hiddenContainer, anchor, isSVG, optimized) {1209 return {1210 vnode,1211 parent,1212 parentComponent,1213 isSVG,1214 optimized,1215 container,1216 hiddenContainer,1217 anchor,1218 deps: 0,1219 subTree: null,1220 fallbackTree: null,1221 isResolved: false,1222 isUnmounted: false,1223 effects: []1224 };1225}1226function normalizeSuspenseChildren(vnode) {1227 const { shapeFlag, children } = vnode;1228 if (shapeFlag & PublicShapeFlags.SLOTS_CHILDREN) {1229 const { default: d, fallback } = children;1230 return {1231 content: normalizeVNode(isFunction(d) ? d() : d),1232 fallback: normalizeVNode(isFunction(fallback) ? fallback() : fallback)1233 };1234 }1235 else {1236 return {1237 content: normalizeVNode(children),1238 fallback: normalizeVNode(null)1239 };1240 }1241}1242const prodEffectOptions = {1243 scheduler: queueJob1244};1245function createDevEffectOptions(instance) {1246 return {1247 scheduler: queueJob,1248 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1249 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01250 };1251}1252function isSameType$1(n1, n2) {1253 return n1.type === n2.type && n1.key === n2.key;1254}1255function invokeHooks(hooks, arg) {1256 for (let i = 0; i < hooks.length; i++) {1257 hooks[i](arg);1258 }1259}1260function queuePostRenderEffect(fn, suspense) {1261 if (suspense !== null && !suspense.isResolved) {1262 if (isArray(fn)) {1263 suspense.effects.push(...fn);1264 }1265 else {1266 suspense.effects.push(fn);1267 }1268 }1269 else {1270 queuePostFlushCb(fn);1271 }1272}1273/**1274 * The createRenderer function accepts two generic arguments:1275 * HostNode and HostElement, corresponding to Node and Element types in the1276 * host environment. For example, for runtime-dom, HostNode would be the DOM1277 * `Node` interface and HostElement would be the DOM `Element` interface.1278 *1279 * Custom renderers can pass in the platform specific types like this:1280 *1281 * ``` js1282 * const { render, createApp } = createRenderer<Node, Element>({1283 * patchProp,1284 * ...nodeOps1285 * })1286 * ```1287 */1288function createRenderer(options) {1289 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1290 function patch(n1, // null means this is a mount1291 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1292 // patching & not same type, unmount old tree1293 if (n1 != null) {1294 if (!isSameType$1(n1, n2)) {1295 anchor = getNextHostNode(n1);1296 unmount(n1, parentComponent, parentSuspense, true);1297 n1 = null;1298 }1299 else if (n1.props && n1.props.$once) {1300 return;1301 }1302 }1303 const { type, shapeFlag } = n2;1304 switch (type) {1305 case Text:1306 processText(n1, n2, container, anchor);1307 break;1308 case Comment:1309 processCommentNode(n1, n2, container, anchor);1310 break;1311 case Fragment:1312 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1313 break;1314 case Portal:1315 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1316 break;1317 case Suspense:1318 {1319 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1320 }1321 break;1322 default:1323 if (shapeFlag & 1 /* ELEMENT */) {1324 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1325 }1326 else if (shapeFlag & 6 /* COMPONENT */) {1327 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1328 }1329 else if (process.env.NODE_ENV !== 'production') {1330 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1331 }1332 }1333 }1334 function processText(n1, n2, container, anchor) {1335 if (n1 == null) {1336 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1337 }1338 else {1339 const el = (n2.el = n1.el);1340 if (n2.children !== n1.children) {1341 hostSetText(el, n2.children);1342 }1343 }1344 }1345 function processCommentNode(n1, n2, container, anchor) {1346 if (n1 == null) {1347 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1348 }1349 else {1350 // there's no support for dynamic comments1351 n2.el = n1.el;1352 }1353 }1354 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1355 if (n1 == null) {1356 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1357 }1358 else {1359 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1360 }1361 if (n2.ref !== null && parentComponent !== null) {1362 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1363 }1364 }1365 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1366 const tag = vnode.type;1367 isSVG = isSVG || tag === 'svg';1368 const el = (vnode.el = hostCreateElement(tag, isSVG));1369 const { props, shapeFlag } = vnode;1370 if (props != null) {1371 for (const key in props) {1372 if (isReservedProp(key))1373 continue;1374 hostPatchProp(el, key, props[key], null, isSVG);1375 }1376 if (props.onVnodeBeforeMount != null) {1377 invokeDirectiveHook(props.onVnodeBeforeMount, parentComponent, vnode);1378 }1379 }1380 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1381 hostSetElementText(el, vnode.children);1382 }1383 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1384 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG, optimized || vnode.dynamicChildren !== null);1385 }1386 hostInsert(el, container, anchor);1387 if (props != null && props.onVnodeMounted != null) {1388 queuePostRenderEffect(() => {1389 invokeDirectiveHook(props.onVnodeMounted, parentComponent, vnode);1390 }, parentSuspense);1391 }1392 }1393 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) {1394 for (let i = start; i < children.length; i++) {1395 const child = optimized1396 ? children[i]1397 : (children[i] = normalizeVNode(children[i]));1398 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1399 }1400 }1401 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {1402 const el = (n2.el = n1.el);1403 const { patchFlag, dynamicChildren } = n2;1404 const oldProps = (n1 && n1.props) || EMPTY_OBJ;1405 const newProps = n2.props || EMPTY_OBJ;1406 if (newProps.onVnodeBeforeUpdate != null) {1407 invokeDirectiveHook(newProps.onVnodeBeforeUpdate, parentComponent, n2, n1);1408 }1409 if (patchFlag > 0) {1410 // the presence of a patchFlag means this element's render code was1411 // generated by the compiler and can take the fast path.1412 // in this path old node and new node are guaranteed to have the same shape1413 // (i.e. at the exact same position in the source template)1414 if (patchFlag & 16 /* FULL_PROPS */) {1415 // element props contain dynamic keys, full diff needed1416 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1417 }1418 else {1419 // class1420 // this flag is matched when the element has dynamic class bindings.1421 if (patchFlag & 2 /* CLASS */) {1422 if (oldProps.class !== newProps.class) {1423 hostPatchProp(el, 'class', newProps.class, null, isSVG);1424 }1425 }1426 // style1427 // this flag is matched when the element has dynamic style bindings1428 if (patchFlag & 4 /* STYLE */) {1429 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);1430 }1431 // props1432 // This flag is matched when the element has dynamic prop/attr bindings1433 // other than class and style. The keys of dynamic prop/attrs are saved for1434 // faster iteration.1435 // Note dynamic keys like :[foo]="bar" will cause this optimization to1436 // bail out and go through a full diff because we need to unset the old key1437 if (patchFlag & 8 /* PROPS */) {1438 // if the flag is present then dynamicProps must be non-null1439 const propsToUpdate = n2.dynamicProps;1440 for (let i = 0; i < propsToUpdate.length; i++) {1441 const key = propsToUpdate[i];1442 const prev = oldProps[key];1443 const next = newProps[key];1444 if (prev !== next) {1445 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);1446 }1447 }1448 }1449 }1450 // text1451 // This flag is matched when the element has only dynamic text children.1452 // this flag is terminal (i.e. skips children diffing).1453 if (patchFlag & 1 /* TEXT */) {1454 if (n1.children !== n2.children) {1455 hostSetElementText(el, n2.children);1456 }1457 return; // terminal1458 }1459 }1460 else if (!optimized && dynamicChildren == null) {1461 // unoptimized, full diff1462 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1463 }1464 if (dynamicChildren != null) {1465 patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, isSVG);1466 }1467 else if (!optimized) {1468 // full diff1469 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);1470 }1471 if (newProps.onVnodeUpdated != null) {1472 queuePostRenderEffect(() => {1473 invokeDirectiveHook(newProps.onVnodeUpdated, parentComponent, n2, n1);1474 }, parentSuspense);1475 }1476 }1477 // The fast path for blocks.1478 function patchBlockChildren(oldChildren, newChildren, fallbackContainer, parentComponent, parentSuspense, isSVG) {1479 for (let i = 0; i < newChildren.length; i++) {1480 const oldVNode = oldChildren[i];1481 patch(oldVNode, newChildren[i], 1482 // in the case of a Fragment, we need to provide the actual parent1483 // of the Fragment itself so it can move its children. In other cases,1484 // the parent container is not actually used so we just pass the1485 // block element here to avoid a DOM parentNode call.1486 oldVNode.type === Fragment1487 ? hostParentNode(oldVNode.el)1488 : fallbackContainer, null, parentComponent, parentSuspense, isSVG, true);1489 }1490 }1491 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {1492 if (oldProps !== newProps) {1493 for (const key in newProps) {1494 if (isReservedProp(key))1495 continue;1496 const next = newProps[key];1497 const prev = oldProps[key];1498 if (next !== prev) {1499 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1500 }1501 }1502 if (oldProps !== EMPTY_OBJ) {1503 for (const key in oldProps) {1504 if (isReservedProp(key))1505 continue;1506 if (!(key in newProps)) {1507 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1508 }1509 }1510 }1511 }1512 }1513 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1514 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));1515 const fragmentEndAnchor = (n2.anchor = n11516 ? n1.anchor1517 : hostCreateComment(''));1518 if (n1 == null) {1519 hostInsert(fragmentStartAnchor, container, anchor);1520 hostInsert(fragmentEndAnchor, container, anchor);1521 // a fragment can only have array children1522 // since they are either generated by the compiler, or implicitly created1523 // from arrays.1524 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);1525 }1526 else {1527 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);1528 }1529 }1530 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1531 const targetSelector = n2.props && n2.props.target;1532 const { patchFlag, shapeFlag, children } = n2;1533 if (n1 == null) {1534 const target = (n2.target = isString(targetSelector)1535 ? hostQuerySelector(targetSelector)1536 : null);1537 if (target != null) {1538 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1539 hostSetElementText(target, children);1540 }1541 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1542 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG, optimized);1543 }1544 }1545 else if (process.env.NODE_ENV !== 'production') {1546 warn('Invalid Portal target on mount:', target, `(${typeof target})`);1547 }1548 }1549 else {1550 // update content1551 const target = (n2.target = n1.target);1552 if (patchFlag === 1 /* TEXT */) {1553 hostSetElementText(target, children);1554 }1555 else if (n2.dynamicChildren) {1556 // fast path when the portal happens to be a block root1557 patchBlockChildren(n1.dynamicChildren, n2.dynamicChildren, container, parentComponent, parentSuspense, isSVG);1558 }1559 else if (!optimized) {1560 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);1561 }1562 // target changed1563 if (targetSelector !== (n1.props && n1.props.target)) {1564 const nextTarget = (n2.target = isString(targetSelector)1565 ? hostQuerySelector(targetSelector)1566 : null);1567 if (nextTarget != null) {1568 // move content1569 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1570 hostSetElementText(target, '');1571 hostSetElementText(nextTarget, children);1572 }1573 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1574 for (let i = 0; i < children.length; i++) {1575 move(children[i], nextTarget, null);1576 }1577 }1578 }1579 else if (process.env.NODE_ENV !== 'production') {1580 warn('Invalid Portal target on update:', target, `(${typeof target})`);1581 }1582 }1583 }1584 // insert an empty node as the placeholder for the portal1585 processCommentNode(n1, n2, container, anchor);1586 }1587 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1588 if (n1 == null) {1589 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1590 }1591 else {1592 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);1593 }1594 }1595 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1596 const hiddenContainer = hostCreateElement('div');1597 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));1598 const { content, fallback } = normalizeSuspenseChildren(n2);1599 suspense.subTree = content;1600 suspense.fallbackTree = fallback;1601 // start mounting the content subtree in an off-dom container1602 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1603 // now check if we have encountered any async deps1604 if (suspense.deps > 0) {1605 // mount the fallback tree1606 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1607 isSVG, optimized);1608 n2.el = fallback.el;1609 }1610 else {1611 // Suspense has no async deps. Just resolve.1612 resolveSuspense(suspense);1613 }1614 }1615 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {1616 const suspense = (n2.suspense = n1.suspense);1617 suspense.vnode = n2;1618 const { content, fallback } = normalizeSuspenseChildren(n2);1619 const oldSubTree = suspense.subTree;1620 const oldFallbackTree = suspense.fallbackTree;1621 if (!suspense.isResolved) {1622 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1623 if (suspense.deps > 0) {1624 // still pending. patch the fallback tree.1625 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1626 isSVG, optimized);1627 n2.el = fallback.el;1628 }1629 // If deps somehow becomes 0 after the patch it means the patch caused an1630 // async dep component to unmount and removed its dep. It will cause the1631 // suspense to resolve and we don't need to do anything here.1632 }1633 else {1634 // just normal patch inner content as a fragment1635 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);1636 n2.el = content.el;1637 }1638 suspense.subTree = content;1639 suspense.fallbackTree = fallback;1640 }1641 function resolveSuspense(suspense) {1642 if (process.env.NODE_ENV !== 'production') {1643 if (suspense.isResolved) {1644 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);1645 }1646 if (suspense.isUnmounted) {1647 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);1648 }1649 }1650 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;1651 // this is initial anchor on mount1652 let { anchor } = suspense;1653 // unmount fallback tree1654 if (fallbackTree.el) {1655 // if the fallback tree was mounted, it may have been moved1656 // as part of a parent suspense. get the latest anchor for insertion1657 anchor = getNextHostNode(fallbackTree);1658 unmount(fallbackTree, parentComponent, suspense, true);1659 }1660 // move content from off-dom container to actual container1661 move(subTree, container, anchor);1662 const el = (vnode.el = subTree.el);1663 // suspense as the root node of a component...1664 if (parentComponent && parentComponent.subTree === vnode) {1665 parentComponent.vnode.el = el;1666 updateHOCHostEl(parentComponent, el);1667 }1668 // check if there is a pending parent suspense1669 let parent = suspense.parent;1670 let hasUnresolvedAncestor = false;1671 while (parent) {1672 if (!parent.isResolved) {1673 // found a pending parent suspense, merge buffered post jobs1674 // into that parent1675 parent.effects.push(...effects);1676 hasUnresolvedAncestor = true;1677 break;1678 }1679 parent = parent.parent;1680 }1681 // no pending parent suspense, flush all jobs1682 if (!hasUnresolvedAncestor) {1683 queuePostFlushCb(effects);1684 }1685 suspense.isResolved = true;1686 // invoke @resolve event1687 const onResolve = vnode.props && vnode.props.onResolve;1688 if (isFunction(onResolve)) {1689 onResolve();1690 }1691 }1692 function restartSuspense(suspense) {1693 suspense.isResolved = false;1694 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;1695 // move content tree back to the off-dom container1696 const anchor = getNextHostNode(subTree);1697 move(subTree, hiddenContainer, null);1698 // remount the fallback tree1699 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context1700 isSVG, optimized);1701 const el = (vnode.el = fallbackTree.el);1702 // suspense as the root node of a component...1703 if (parentComponent && parentComponent.subTree === vnode) {1704 parentComponent.vnode.el = el;1705 updateHOCHostEl(parentComponent, el);1706 }1707 // invoke @suspense event1708 const onSuspense = vnode.props && vnode.props.onSuspense;1709 if (isFunction(onSuspense)) {1710 onSuspense();1711 }1712 }1713 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1714 if (n1 == null) {1715 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);1716 }1717 else {1718 const instance = (n2.component = n1.component);1719 if (shouldUpdateComponent(n1, n2, optimized)) {1720 if (1721 instance.asyncDep &&1722 !instance.asyncResolved) {1723 // async & still pending - just update props and slots1724 // since the component's reactive effect for render isn't set-up yet1725 if (process.env.NODE_ENV !== 'production') {1726 pushWarningContext(n2);1727 }1728 updateComponentPreRender(instance, n2);1729 if (process.env.NODE_ENV !== 'production') {1730 popWarningContext();1731 }1732 return;1733 }1734 else {1735 // normal update1736 instance.next = n2;1737 // instance.update is the reactive effect runner.1738 instance.update();1739 }1740 }1741 else {1742 // no update needed. just copy over properties1743 n2.component = n1.component;1744 n2.el = n1.el;1745 }1746 }1747 if (n2.ref !== null && parentComponent !== null) {1748 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);1749 }1750 }1751 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {1752 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));1753 if (process.env.NODE_ENV !== 'production') {1754 pushWarningContext(initialVNode);1755 }1756 // resolve props and slots for setup context1757 const propsOptions = initialVNode.type.props;1758 resolveProps(instance, initialVNode.props, propsOptions);1759 resolveSlots(instance, initialVNode.children);1760 // setup stateful logic1761 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {1762 setupStatefulComponent(instance, parentSuspense);1763 }1764 // setup() is async. This component relies on async logic to be resolved1765 // before proceeding1766 if ( instance.asyncDep) {1767 if (!parentSuspense) {1768 // TODO handle this properly1769 throw new Error('Async component without a suspense boundary!');1770 }1771 // parent suspense already resolved, need to re-suspense1772 // use queueJob so it's handled synchronously after patching the current1773 // suspense tree1774 if (parentSuspense.isResolved) {1775 queueJob(() => {1776 restartSuspense(parentSuspense);1777 });1778 }1779 parentSuspense.deps++;1780 instance.asyncDep1781 .catch(err => {1782 handleError(err, instance, 0 /* SETUP_FUNCTION */);1783 })1784 .then(asyncSetupResult => {1785 // component may be unmounted before resolve1786 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {1787 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);1788 }1789 });1790 // give it a placeholder1791 const placeholder = (instance.subTree = createVNode(Comment));1792 processCommentNode(null, placeholder, container, anchor);1793 initialVNode.el = placeholder.el;1794 return;1795 }1796 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);1797 if (process.env.NODE_ENV !== 'production') {1798 popWarningContext();1799 }1800 }1801 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {1802 parentSuspense.deps--;1803 // retry from this component1804 instance.asyncResolved = true;1805 const { vnode } = instance;1806 if (process.env.NODE_ENV !== 'production') {1807 pushWarningContext(vnode);1808 }1809 handleSetupResult(instance, asyncSetupResult, parentSuspense);1810 setupRenderEffect(instance, parentSuspense, vnode, 1811 // component may have been moved before resolve1812 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);1813 updateHOCHostEl(instance, vnode.el);1814 if (process.env.NODE_ENV !== 'production') {1815 popWarningContext();1816 }1817 if (parentSuspense.deps === 0) {1818 resolveSuspense(parentSuspense);1819 }1820 }1821 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {1822 // create reactive effect for rendering1823 let mounted = false;1824 instance.update = effect(function componentEffect() {1825 if (!mounted) {1826 const subTree = (instance.subTree = renderComponentRoot(instance));1827 // beforeMount hook1828 if (instance.bm !== null) {1829 invokeHooks(instance.bm);1830 }1831 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);1832 initialVNode.el = subTree.el;1833 // mounted hook1834 if (instance.m !== null) {1835 queuePostRenderEffect(instance.m, parentSuspense);1836 }1837 mounted = true;1838 }1839 else {1840 // updateComponent1841 // This is triggered by mutation of component's own state (next: null)1842 // OR parent calling processComponent (next: HostVNode)1843 const { next } = instance;1844 if (process.env.NODE_ENV !== 'production') {1845 pushWarningContext(next || instance.vnode);1846 }1847 if (next !== null) {1848 updateComponentPreRender(instance, next);1849 }1850 const prevTree = instance.subTree;1851 const nextTree = (instance.subTree = renderComponentRoot(instance));1852 // beforeUpdate hook1853 if (instance.bu !== null) {1854 invokeHooks(instance.bu);1855 }1856 // reset refs1857 // only needed if previous patch had refs1858 if (instance.refs !== EMPTY_OBJ) {1859 instance.refs = {};1860 }1861 patch(prevTree, nextTree, 1862 // parent may have changed if it's in a portal1863 hostParentNode(prevTree.el), 1864 // anchor may have changed if it's in a fragment1865 getNextHostNode(prevTree), instance, parentSuspense, isSVG);1866 instance.vnode.el = nextTree.el;1867 if (next === null) {1868 // self-triggered update. In case of HOC, update parent component1869 // vnode el. HOC is indicated by parent instance's subTree pointing1870 // to child component's vnode1871 updateHOCHostEl(instance, nextTree.el);1872 }1873 // updated hook1874 if (instance.u !== null) {1875 queuePostRenderEffect(instance.u, parentSuspense);1876 }1877 if (process.env.NODE_ENV !== 'production') {1878 popWarningContext();1879 }1880 }1881 }, process.env.NODE_ENV !== 'production' ? createDevEffectOptions(instance) : prodEffectOptions);1882 }1883 function updateComponentPreRender(instance, nextVNode) {1884 nextVNode.component = instance;1885 instance.vnode = nextVNode;1886 instance.next = null;1887 resolveProps(instance, nextVNode.props, nextVNode.type.props);1888 resolveSlots(instance, nextVNode.children);1889 }1890 function updateHOCHostEl({ vnode, parent }, el) {1891 while (parent && parent.subTree === vnode) {1892 (vnode = parent.vnode).el = el;1893 parent = parent.parent;1894 }1895 }1896 function patchChildren(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized = false) {1897 const c1 = n1 && n1.children;1898 const prevShapeFlag = n1 ? n1.shapeFlag : 0;1899 const c2 = n2.children;1900 const { patchFlag, shapeFlag } = n2;1901 if (patchFlag === -1 /* BAIL */) {1902 optimized = false;1903 }1904 // fast path1905 if (patchFlag > 0) {1906 if (patchFlag & 64 /* KEYED_FRAGMENT */) {1907 // this could be either fully-keyed or mixed (some keyed some not)1908 // presence of patchFlag means children are guaranteed to be arrays1909 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1910 return;1911 }1912 else if (patchFlag & 128 /* UNKEYED_FRAGMENT */) {1913 // unkeyed1914 patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1915 return;1916 }1917 }1918 // children has 3 possibilities: text, array or no children.1919 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1920 // text children fast path1921 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {1922 unmountChildren(c1, parentComponent, parentSuspense);1923 }1924 if (c2 !== c1) {1925 hostSetElementText(container, c2);1926 }1927 }1928 else {1929 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {1930 // prev children was array1931 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1932 // two arrays, cannot assume anything, do full diff1933 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1934 }1935 else {1936 // no new children, just unmount old1937 unmountChildren(c1, parentComponent, parentSuspense, true);1938 }1939 }1940 else {1941 // prev children was text OR null1942 // new children is array OR null1943 if (prevShapeFlag & 8 /* TEXT_CHILDREN */) {1944 hostSetElementText(container, '');1945 }1946 // mount new if array1947 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1948 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1949 }1950 }1951 }1952 }1953 function patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1954 c1 = c1 || EMPTY_ARR;1955 c2 = c2 || EMPTY_ARR;1956 const oldLength = c1.length;1957 const newLength = c2.length;1958 const commonLength = Math.min(oldLength, newLength);1959 let i;1960 for (i = 0; i < commonLength; i++) {1961 const nextChild = optimized1962 ? c2[i]1963 : (c2[i] = normalizeVNode(c2[i]));1964 patch(c1[i], nextChild, container, null, parentComponent, parentSuspense, isSVG, optimized);1965 }1966 if (oldLength > newLength) {1967 // remove old1968 unmountChildren(c1, parentComponent, parentSuspense, true, commonLength);1969 }1970 else {1971 // mount new1972 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, commonLength);1973 }1974 }1975 // can be all-keyed or mixed1976 function patchKeyedChildren(c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) {1977 let i = 0;1978 const l2 = c2.length;1979 let e1 = c1.length - 1; // prev ending index1980 let e2 = l2 - 1; // next ending index1981 // 1. sync from start1982 // (a b) c1983 // (a b) d e1984 while (i <= e1 && i <= e2) {1985 const n1 = c1[i];1986 const n2 = optimized1987 ? c2[i]1988 : (c2[i] = normalizeVNode(c2[i]));1989 if (isSameType$1(n1, n2)) {1990 patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);1991 }1992 else {1993 break;1994 }1995 i++;1996 }1997 // 2. sync from end1998 // a (b c)1999 // d e (b c)2000 while (i <= e1 && i <= e2) {2001 const n1 = c1[e1];2002 const n2 = optimized2003 ? c2[i]2004 : (c2[e2] = normalizeVNode(c2[e2]));2005 if (isSameType$1(n1, n2)) {2006 patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);2007 }2008 else {2009 break;2010 }2011 e1--;2012 e2--;2013 }2014 // 3. common sequence + mount2015 // (a b)2016 // (a b) c2017 // i = 2, e1 = 1, e2 = 22018 // (a b)2019 // c (a b)2020 // i = 0, e1 = -1, e2 = 02021 if (i > e1) {2022 if (i <= e2) {2023 const nextPos = e2 + 1;2024 const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;2025 while (i <= e2) {2026 patch(null, optimized ? c2[i] : (c2[i] = normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);2027 i++;2028 }2029 }2030 }2031 // 4. common sequence + unmount2032 // (a b) c2033 // (a b)2034 // i = 2, e1 = 2, e2 = 12035 // a (b c)2036 // (b c)2037 // i = 0, e1 = 0, e2 = -12038 else if (i > e2) {2039 while (i <= e1) {2040 unmount(c1[i], parentComponent, parentSuspense, true);2041 i++;2042 }2043 }2044 // 5. unknown sequence2045 // [i ... e1 + 1]: a b [c d e] f g2046 // [i ... e2 + 1]: a b [e d c h] f g2047 // i = 2, e1 = 4, e2 = 52048 else {2049 const s1 = i; // prev starting index2050 const s2 = i; // next starting index2051 // 5.1 build key:index map for newChildren2052 const keyToNewIndexMap = new Map();2053 for (i = s2; i <= e2; i++) {2054 const nextChild = optimized2055 ? c2[i]2056 : (c2[i] = normalizeVNode(c2[i]));2057 if (nextChild.key != null) {2058 if (process.env.NODE_ENV !== 'production' && keyToNewIndexMap.has(nextChild.key)) {2059 warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);2060 }2061 keyToNewIndexMap.set(nextChild.key, i);2062 }2063 }2064 // 5.2 loop through old children left to be patched and try to patch2065 // matching nodes & remove nodes that are no longer present2066 let j;2067 let patched = 0;2068 const toBePatched = e2 - s2 + 1;2069 let moved = false;2070 // used to track whether any node has moved2071 let maxNewIndexSoFar = 0;2072 // works as Map<newIndex, oldIndex>2073 // Note that oldIndex is offset by +12074 // and oldIndex = 0 is a special value indicating the new node has2075 // no corresponding old node.2076 // used for determining longest stable subsequence2077 const newIndexToOldIndexMap = new Array(toBePatched);2078 for (i = 0; i < toBePatched; i++)2079 newIndexToOldIndexMap[i] = 0;2080 for (i = s1; i <= e1; i++) {2081 const prevChild = c1[i];2082 if (patched >= toBePatched) {2083 // all new children have been patched so this can only be a removal2084 unmount(prevChild, parentComponent, parentSuspense, true);2085 continue;2086 }2087 let newIndex;2088 if (prevChild.key != null) {2089 newIndex = keyToNewIndexMap.get(prevChild.key);2090 }2091 else {2092 // key-less node, try to locate a key-less node of the same type2093 for (j = s2; j <= e2; j++) {2094 if (newIndexToOldIndexMap[j - s2] === 0 &&2095 isSameType$1(prevChild, c2[j])) {2096 newIndex = j;2097 break;2098 }2099 }2100 }2101 if (newIndex === undefined) {2102 unmount(prevChild, parentComponent, parentSuspense, true);2103 }2104 else {2105 newIndexToOldIndexMap[newIndex - s2] = i + 1;2106 if (newIndex >= maxNewIndexSoFar) {2107 maxNewIndexSoFar = newIndex;2108 }2109 else {2110 moved = true;2111 }2112 patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);2113 patched++;2114 }2115 }2116 // 5.3 move and mount2117 // generate longest stable subsequence only when nodes have moved2118 const increasingNewIndexSequence = moved2119 ? getSequence(newIndexToOldIndexMap)2120 : EMPTY_ARR;2121 j = increasingNewIndexSequence.length - 1;2122 // looping backwards so that we can use last patched node as anchor2123 for (i = toBePatched - 1; i >= 0; i--) {2124 const nextIndex = s2 + i;2125 const nextChild = c2[nextIndex];2126 const anchor = nextIndex + 1 < l22127 ? c2[nextIndex + 1].el2128 : parentAnchor;2129 if (newIndexToOldIndexMap[i] === 0) {2130 // mount new2131 patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);2132 }2133 else if (moved) {2134 // move if:2135 // There is no stable subsequence (e.g. a reverse)2136 // OR current node is not among the stable sequence2137 if (j < 0 || i !== increasingNewIndexSequence[j]) {2138 move(nextChild, container, anchor);2139 }2140 else {2141 j--;2142 }2143 }2144 }2145 }2146 }2147 function move(vnode, container, anchor) {2148 if (vnode.component !== null) {2149 move(vnode.component.subTree, container, anchor);2150 return;2151 }2152 if ( vnode.type === Suspense) {2153 const suspense = vnode.suspense;2154 move(suspense.isResolved ? suspense.subTree : suspense.fallbackTree, container, anchor);2155 suspense.container = container;2156 return;2157 }2158 if (vnode.type === Fragment) {2159 hostInsert(vnode.el, container, anchor);2160 const children = vnode.children;2161 for (let i = 0; i < children.length; i++) {2162 move(children[i], container, anchor);2163 }2164 hostInsert(vnode.anchor, container, anchor);2165 }2166 else {2167 hostInsert(vnode.el, container, anchor);2168 }2169 }2170 function unmount(vnode, parentComponent, parentSuspense, doRemove) {2171 const { props, ref, type, component, suspense, children, dynamicChildren, shapeFlag, anchor } = vnode;2172 // unset ref2173 if (ref !== null && parentComponent !== null) {2174 setRef(ref, null, parentComponent, null);2175 }2176 if (component != null) {2177 unmountComponent(component, parentSuspense, doRemove);2178 return;2179 }2180 if ( suspense != null) {2181 unmountSuspense(suspense, parentComponent, parentSuspense, doRemove);2182 return;2183 }2184 if (props != null && props.onVnodeBeforeUnmount != null) {2185 invokeDirectiveHook(props.onVnodeBeforeUnmount, parentComponent, vnode);2186 }2187 const shouldRemoveChildren = type === Fragment && doRemove;2188 if (dynamicChildren != null) {2189 unmountChildren(dynamicChildren, parentComponent, parentSuspense, shouldRemoveChildren);2190 }2191 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2192 unmountChildren(children, parentComponent, parentSuspense, shouldRemoveChildren);2193 }2194 if (doRemove) {2195 hostRemove(vnode.el);2196 if (anchor != null)2197 hostRemove(anchor);2198 }2199 if (props != null && props.onVnodeUnmounted != null) {2200 queuePostRenderEffect(() => {2201 invokeDirectiveHook(props.onVnodeUnmounted, parentComponent, vnode);2202 }, parentSuspense);2203 }2204 }2205 function unmountComponent(instance, parentSuspense, doRemove) {2206 const { bum, effects, update, subTree, um } = instance;2207 // beforeUnmount hook2208 if (bum !== null) {2209 invokeHooks(bum);2210 }2211 if (effects !== null) {2212 for (let i = 0; i < effects.length; i++) {2213 stop(effects[i]);2214 }2215 }2216 // update may be null if a component is unmounted before its async2217 // setup has resolved.2218 if (update !== null) {2219 stop(update);2220 unmount(subTree, instance, parentSuspense, doRemove);2221 }2222 // unmounted hook2223 if (um !== null) {2224 queuePostRenderEffect(um, parentSuspense);2225 }2226 queuePostFlushCb(() => {2227 instance.isUnmounted = true;2228 });2229 // A component with async dep inside a pending suspense is unmounted before2230 // its async dep resolves. This should remove the dep from the suspense, and2231 // cause the suspense to resolve immediately if that was the last dep.2232 if (2233 parentSuspense !== null &&2234 !parentSuspense.isResolved &&2235 !parentSuspense.isUnmounted &&2236 instance.asyncDep !== null &&2237 !instance.asyncResolved) {2238 parentSuspense.deps--;2239 if (parentSuspense.deps === 0) {2240 resolveSuspense(parentSuspense);2241 }2242 }2243 }2244 function unmountSuspense(suspense, parentComponent, parentSuspense, doRemove) {2245 suspense.isUnmounted = true;2246 unmount(suspense.subTree, parentComponent, parentSuspense, doRemove);2247 if (!suspense.isResolved) {2248 unmount(suspense.fallbackTree, parentComponent, parentSuspense, doRemove);2249 }2250 }2251 function unmountChildren(children, parentComponent, parentSuspense, doRemove, start = 0) {2252 for (let i = start; i < children.length; i++) {2253 unmount(children[i], parentComponent, parentSuspense, doRemove);2254 }2255 }2256 function getNextHostNode({ component, suspense, anchor, el }) {2257 if (component !== null) {2258 return getNextHostNode(component.subTree);2259 }2260 if ( suspense !== null) {2261 return getNextHostNode(suspense.isResolved ? suspense.subTree : suspense.fallbackTree);2262 }2263 return hostNextSibling((anchor || el));2264 }2265 function setRef(ref, oldRef, parent, value) {2266 const refs = parent.refs === EMPTY_OBJ ? (parent.refs = {}) : parent.refs;2267 const renderContext = toRaw(parent.renderContext);2268 // unset old ref2269 if (oldRef !== null && oldRef !== ref) {2270 if (isString(oldRef)) {2271 refs[oldRef] = null;2272 const oldSetupRef = renderContext[oldRef];2273 if (isRef(oldSetupRef)) {2274 oldSetupRef.value = null;2275 }2276 }2277 else if (isRef(oldRef)) {2278 oldRef.value = null;2279 }2280 }2281 if (isString(ref)) {2282 const setupRef = renderContext[ref];2283 if (isRef(setupRef)) {2284 setupRef.value = value;2285 }2286 refs[ref] = value;2287 }2288 else if (isRef(ref)) {2289 ref.value = value;2290 }2291 else if (isFunction(ref)) {2292 ref(value, refs);2293 }2294 else if (process.env.NODE_ENV !== 'production') {2295 warn('Invalid template ref type:', value, `(${typeof value})`);2296 }2297 }2298 function render(vnode, rawContainer) {2299 let container = rawContainer;2300 if (isString(container)) {2301 container = hostQuerySelector(container);2302 if (!container) {2303 if (process.env.NODE_ENV !== 'production') {2304 warn(`Failed to locate root container: ` + `querySelector returned null.`);2305 }2306 return;2307 }2308 }2309 if (vnode == null) {2310 if (container._vnode) {2311 unmount(container._vnode, null, null, true);2312 }2313 }2314 else {2315 patch(container._vnode || null, vnode, container);2316 }2317 flushPostFlushCbs();2318 container._vnode = vnode;2319 }2320 return {2321 render,2322 createApp: createAppAPI(render)2323 };2324}2325// https://en.wikipedia.org/wiki/Longest_increasing_subsequence2326function getSequence(arr) {2327 const p = arr.slice();2328 const result = [0];2329 let i, j, u, v, c;2330 const len = arr.length;2331 for (i = 0; i < len; i++) {2332 const arrI = arr[i];2333 if (arrI !== 0) {2334 j = result[result.length - 1];2335 if (arr[j] < arrI) {2336 p[i] = j;2337 result.push(i);2338 continue;2339 }2340 u = 0;2341 v = result.length - 1;2342 while (u < v) {2343 c = ((u + v) / 2) | 0;2344 if (arr[result[c]] < arrI) {2345 u = c + 1;2346 }2347 else {2348 v = c;2349 }2350 }2351 if (arrI < arr[result[u]]) {2352 if (u > 0) {2353 p[i] = result[u - 1];2354 }2355 result[u] = i;2356 }2357 }2358 }2359 u = result.length;2360 v = result[u - 1];2361 while (u-- > 0) {2362 result[u] = v;2363 v = p[v];2364 }2365 return result;2366}2367const invoke = (fn) => fn();2368// implementation2369function watch(effectOrSource, cbOrOptions, options) {2370 if (isFunction(cbOrOptions)) {2371 // effect callback as 2nd argument - this is a source watcher2372 return doWatch(effectOrSource, cbOrOptions, options);2373 }2374 else {2375 // 2nd argument is either missing or an options object2376 // - this is a simple effect watcher2377 return doWatch(effectOrSource, null, cbOrOptions);2378 }2379}2380function doWatch(source, cb, { lazy, deep, flush, onTrack, onTrigger } = EMPTY_OBJ) {2381 const instance = currentInstance;2382 const suspense = currentSuspense;2383 let getter;2384 if (isArray(source)) {2385 getter = () => source.map(s => isRef(s)2386 ? s.value2387 : callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */));2388 }2389 else if (isRef(source)) {2390 getter = () => source.value;2391 }2392 else if (cb) {2393 // getter with cb2394 getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */);2395 }2396 else {2397 // no cb -> simple effect2398 getter = () => {2399 if (instance && instance.isUnmounted) {2400 return;2401 }2402 if (cleanup) {2403 cleanup();2404 }2405 return callWithErrorHandling(source, instance, 3 /* WATCH_CALLBACK */, [registerCleanup]);2406 };2407 }2408 if (deep) {2409 const baseGetter = getter;2410 getter = () => traverse(baseGetter());2411 }2412 let cleanup;2413 const registerCleanup = (fn) => {2414 // TODO wrap the cleanup fn for error handling2415 cleanup = runner.onStop = () => {2416 callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */);2417 };2418 };2419 let oldValue = isArray(source) ? [] : undefined;2420 const applyCb = cb2421 ? () => {2422 if (instance && instance.isUnmounted) {2423 return;2424 }2425 const newValue = runner();2426 if (deep || newValue !== oldValue) {2427 // cleanup before running cb again2428 if (cleanup) {2429 cleanup();2430 }2431 callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [2432 newValue,2433 oldValue,2434 registerCleanup2435 ]);2436 oldValue = newValue;2437 }2438 }2439 : void 0;2440 let scheduler;2441 if (flush === 'sync') {2442 scheduler = invoke;2443 }2444 else if (flush === 'pre') {2445 scheduler = job => {2446 if (!instance || instance.vnode.el != null) {2447 queueJob(job);2448 }2449 else {2450 // with 'pre' option, the first call must happen before2451 // the component is mounted so it is called synchronously.2452 job();2453 }2454 };2455 }2456 else {2457 scheduler = job => {2458 queuePostRenderEffect(job, suspense);2459 };2460 }2461 const runner = effect(getter, {2462 lazy: true,2463 // so it runs before component update effects in pre flush mode2464 computed: true,2465 onTrack,2466 onTrigger,2467 scheduler: applyCb ? () => scheduler(applyCb) : scheduler2468 });2469 if (!lazy) {2470 if (applyCb) {2471 scheduler(applyCb);2472 }2473 else {2474 scheduler(runner);2475 }2476 }2477 else {2478 oldValue = runner();2479 }2480 recordEffect(runner);2481 return () => {2482 stop(runner);2483 };2484}2485// this.$watch2486function instanceWatch(source, cb, options) {2487 const ctx = this.renderProxy;2488 const getter = isString(source) ? () => ctx[source] : source.bind(ctx);2489 const stop = watch(getter, cb.bind(ctx), options);2490 onBeforeUnmount(stop, this);2491 return stop;2492}2493function traverse(value, seen = new Set()) {2494 if (!isObject(value) || seen.has(value)) {2495 return;2496 }2497 seen.add(value);2498 if (isArray(value)) {2499 for (let i = 0; i < value.length; i++) {2500 traverse(value[i], seen);2501 }2502 }2503 else if (value instanceof Map) {2504 value.forEach((v, key) => {2505 // to register mutation dep for existing keys2506 traverse(value.get(key), seen);2507 });2508 }2509 else if (value instanceof Set) {2510 value.forEach(v => {2511 traverse(v, seen);2512 });2513 }2514 else {2515 for (const key in value) {2516 traverse(value[key], seen);2517 }2518 }2519 return value;2520}2521const publicPropertiesMap = {2522 $data: 'data',2523 $props: 'propsProxy',2524 $attrs: 'attrs',2525 $slots: 'slots',2526 $refs: 'refs',2527 $parent: 'parent',2528 $root: 'root',2529 $emit: 'emit',2530 $options: 'type'2531};2532const PublicInstanceProxyHandlers = {2533 get(target, key) {2534 const { renderContext, data, props, propsProxy, accessCache, type } = target;2535 // This getter gets called for every property access on the render context2536 // during render and is a major hotspot. The most expensive part of this2537 // is the multiple hasOwn() calls. It's much faster to do a simple property2538 // access on a plain object, so we use an accessCache object (with null2539 // prototype) to memoize what access type a key corresponds to.2540 const n = accessCache[key];2541 if (n !== undefined) {2542 switch (n) {2543 case 0 /* DATA */:2544 return data[key];2545 case 1 /* CONTEXT */:2546 return renderContext[key];2547 case 2 /* PROPS */:2548 return propsProxy[key];2549 }2550 }2551 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {2552 accessCache[key] = 0 /* DATA */;2553 return data[key];2554 }2555 else if (hasOwn(renderContext, key)) {2556 accessCache[key] = 1 /* CONTEXT */;2557 return renderContext[key];2558 }2559 else if (hasOwn(props, key)) {2560 // only cache props access if component has declared (thus stable) props2561 if (type.props != null) {2562 accessCache[key] = 2 /* PROPS */;2563 }2564 // return the value from propsProxy for ref unwrapping and readonly2565 return propsProxy[key];2566 }2567 else if (key === '$cache') {2568 return target.renderCache || (target.renderCache = []);2569 }2570 else if (key === '$el') {2571 return target.vnode.el;2572 }2573 else if (hasOwn(publicPropertiesMap, key)) {2574 return target[publicPropertiesMap[key]];2575 }2576 // methods are only exposed when options are supported2577 {2578 switch (key) {2579 case '$forceUpdate':2580 return target.update;2581 case '$nextTick':2582 return nextTick;2583 case '$watch':2584 return instanceWatch.bind(target);2585 }2586 }2587 return target.user[key];2588 },2589 set(target, key, value) {2590 const { data, renderContext } = target;2591 if (data !== EMPTY_OBJ && hasOwn(data, key)) {2592 data[key] = value;2593 }2594 else if (hasOwn(renderContext, key)) {2595 renderContext[key] = value;2596 }2597 else if (key[0] === '$' && key.slice(1) in target) {2598 process.env.NODE_ENV !== 'production' &&2599 warn(`Attempting to mutate public property "${key}". ` +2600 `Properties starting with $ are reserved and readonly.`, target);2601 return false;2602 }2603 else if (key in target.props) {2604 process.env.NODE_ENV !== 'production' &&2605 warn(`Attempting to mutate prop "${key}". Props are readonly.`, target);2606 return false;2607 }2608 else {2609 target.user[key] = value;2610 }2611 return true;2612 }2613};2614function provide(key, value) {2615 if (!currentInstance) {2616 if (process.env.NODE_ENV !== 'production') {2617 warn(`provide() can only be used inside setup().`);2618 }2619 }2620 else {2621 let provides = currentInstance.provides;2622 // by default an instance inherits its parent's provides object2623 // but when it needs to provide values of its own, it creates its2624 // own provides object using parent provides object as prototype.2625 // this way in `inject` we can simply look up injections from direct2626 // parent and let the prototype chain do the work.2627 const parentProvides = currentInstance.parent && currentInstance.parent.provides;2628 if (parentProvides === provides) {2629 provides = currentInstance.provides = Object.create(parentProvides);2630 }2631 // TS doesn't allow symbol as index type2632 provides[key] = value;2633 }2634}2635function inject(key, defaultValue) {2636 if (currentInstance) {2637 const provides = currentInstance.provides;2638 if (key in provides) {2639 // TS doesn't allow symbol as index type2640 return provides[key];2641 }2642 else if (defaultValue !== undefined) {2643 return defaultValue;2644 }2645 else if (process.env.NODE_ENV !== 'production') {2646 warn(`injection "${key}" not found.`);2647 }2648 }2649 else if (process.env.NODE_ENV !== 'production') {2650 warn(`inject() can only be used inside setup().`);2651 }2652}2653function applyOptions(instance, options, asMixin = false) {2654 const renderContext = instance.renderContext === EMPTY_OBJ2655 ? (instance.renderContext = reactive({}))2656 : instance.renderContext;2657 const ctx = instance.renderProxy;2658 const { 2659 // composition2660 mixins, extends: extendsOptions, 2661 // state2662 data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions, 2663 // assets2664 components, directives, 2665 // lifecycle2666 beforeMount, mounted, beforeUpdate, updated, 2667 // TODO activated2668 // TODO deactivated2669 beforeUnmount, unmounted, renderTracked, renderTriggered, errorCaptured } = options;2670 const globalMixins = instance.appContext.mixins;2671 // applyOptions is called non-as-mixin once per instance2672 if (!asMixin) {2673 callSyncHook('beforeCreate', options, ctx, globalMixins);2674 // global mixins are applied first2675 applyMixins(instance, globalMixins);2676 }2677 // extending a base component...2678 if (extendsOptions) {2679 applyOptions(instance, extendsOptions, true);2680 }2681 // local mixins2682 if (mixins) {2683 applyMixins(instance, mixins);2684 }2685 // state options2686 if (dataOptions) {2687 const data = isFunction(dataOptions) ? dataOptions.call(ctx) : dataOptions;2688 if (!isObject(data)) {2689 process.env.NODE_ENV !== 'production' && warn(`data() should return an object.`);2690 }2691 else if (instance.data === EMPTY_OBJ) {2692 instance.data = reactive(data);2693 }2694 else {2695 // existing data: this is a mixin or extends.2696 extend(instance.data, data);2697 }2698 }2699 if (computedOptions) {2700 for (const key in computedOptions) {2701 const opt = computedOptions[key];2702 if (isFunction(opt)) {2703 renderContext[key] = computed(opt.bind(ctx));2704 }2705 else {2706 const { get, set } = opt;2707 if (isFunction(get)) {2708 renderContext[key] = computed({2709 get: get.bind(ctx),2710 set: isFunction(set)2711 ? set.bind(ctx)2712 : process.env.NODE_ENV !== 'production'2713 ? () => {2714 warn(`Computed property "${key}" was assigned to but it has no setter.`);2715 }2716 : NOOP2717 });2718 }2719 else if (process.env.NODE_ENV !== 'production') {2720 warn(`Computed property "${key}" has no getter.`);2721 }2722 }2723 }2724 }2725 if (methods) {2726 for (const key in methods) {2727 renderContext[key] = methods[key].bind(ctx);2728 }2729 }2730 if (watchOptions) {2731 for (const key in watchOptions) {2732 const raw = watchOptions[key];2733 const getter = () => ctx[key];2734 if (isString(raw)) {2735 const handler = renderContext[raw];2736 if (isFunction(handler)) {2737 watch(getter, handler);2738 }2739 else if (process.env.NODE_ENV !== 'production') {2740 warn(`Invalid watch handler specified by key "${raw}"`, handler);2741 }2742 }2743 else if (isFunction(raw)) {2744 watch(getter, raw.bind(ctx));2745 }2746 else if (isObject(raw)) {2747 // TODO 2.x compat2748 watch(getter, raw.handler.bind(ctx), raw);2749 }2750 else if (process.env.NODE_ENV !== 'production') {2751 warn(`Invalid watch option: "${key}"`);2752 }2753 }2754 }2755 if (provideOptions) {2756 const provides = isFunction(provideOptions)2757 ? provideOptions.call(ctx)2758 : provideOptions;2759 for (const key in provides) {2760 provide(key, provides[key]);2761 }2762 }2763 if (injectOptions) {2764 if (isArray(injectOptions)) {2765 for (let i = 0; i < injectOptions.length; i++) {2766 const key = injectOptions[i];2767 renderContext[key] = inject(key);2768 }2769 }2770 else {2771 for (const key in injectOptions) {2772 const opt = injectOptions[key];2773 if (isObject(opt)) {2774 renderContext[key] = inject(opt.from, opt.default);2775 }2776 else {2777 renderContext[key] = inject(opt);2778 }2779 }2780 }2781 }2782 // asset options2783 if (components) {2784 extend(instance.components, components);2785 }2786 if (directives) {2787 extend(instance.directives, directives);2788 }2789 // lifecycle options2790 if (!asMixin) {2791 callSyncHook('created', options, ctx, globalMixins);2792 }2793 if (beforeMount) {2794 onBeforeMount(beforeMount.bind(ctx));2795 }2796 if (mounted) {2797 onMounted(mounted.bind(ctx));2798 }2799 if (beforeUpdate) {2800 onBeforeUpdate(beforeUpdate.bind(ctx));2801 }2802 if (updated) {2803 onUpdated(updated.bind(ctx));2804 }2805 if (errorCaptured) {2806 onErrorCaptured(errorCaptured.bind(ctx));2807 }2808 if (renderTracked) {2809 onRenderTracked(renderTracked.bind(ctx));2810 }2811 if (renderTriggered) {2812 onRenderTriggered(renderTriggered.bind(ctx));2813 }2814 if (beforeUnmount) {2815 onBeforeUnmount(beforeUnmount.bind(ctx));2816 }2817 if (unmounted) {2818 onUnmounted(unmounted.bind(ctx));2819 }2820}2821function callSyncHook(name, options, ctx, globalMixins) {2822 callHookFromMixins(name, globalMixins, ctx);2823 const baseHook = options.extends && options.extends[name];2824 if (baseHook) {2825 baseHook.call(ctx);2826 }2827 const mixins = options.mixins;2828 if (mixins) {2829 callHookFromMixins(name, mixins, ctx);2830 }2831 const selfHook = options[name];2832 if (selfHook) {2833 selfHook.call(ctx);2834 }2835}2836function callHookFromMixins(name, mixins, ctx) {2837 for (let i = 0; i < mixins.length; i++) {2838 const fn = mixins[i][name];2839 if (fn) {2840 fn.call(ctx);2841 }2842 }2843}2844function applyMixins(instance, mixins) {2845 for (let i = 0; i < mixins.length; i++) {2846 applyOptions(instance, mixins[i], true);2847 }2848}2849const emptyAppContext = createAppContext();2850function createComponentInstance(vnode, parent) {2851 // inherit parent app context - or - if root, adopt from root vnode2852 const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext;2853 const instance = {2854 vnode,2855 parent,2856 appContext,2857 type: vnode.type,2858 root: null,2859 next: null,2860 subTree: null,2861 update: null,2862 render: null,2863 renderProxy: null,2864 propsProxy: null,2865 setupContext: null,2866 effects: null,2867 provides: parent ? parent.provides : Object.create(appContext.provides),2868 accessCache: null,2869 renderCache: null,2870 // setup context properties2871 renderContext: EMPTY_OBJ,2872 data: EMPTY_OBJ,2873 props: EMPTY_OBJ,2874 attrs: EMPTY_OBJ,2875 slots: EMPTY_OBJ,2876 refs: EMPTY_OBJ,2877 // per-instance asset storage (mutable during options resolution)2878 components: Object.create(appContext.components),2879 directives: Object.create(appContext.directives),2880 // async dependency management2881 asyncDep: null,2882 asyncResult: null,2883 asyncResolved: false,2884 // user namespace for storing whatever the user assigns to `this`2885 user: {},2886 // lifecycle hooks2887 // not using enums here because it results in computed properties2888 isUnmounted: false,2889 bc: null,2890 c: null,2891 bm: null,2892 m: null,2893 bu: null,2894 u: null,2895 um: null,2896 bum: null,2897 da: null,2898 a: null,2899 rtg: null,2900 rtc: null,2901 ec: null,2902 emit: (event, ...args) => {2903 const props = instance.vnode.props || EMPTY_OBJ;2904 const handler = props[`on${event}`] || props[`on${capitalize(event)}`];2905 if (handler) {2906 callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args);2907 }2908 }2909 };2910 instance.root = parent ? parent.root : instance;2911 return instance;2912}2913let currentInstance = null;2914let currentSuspense = null;2915const getCurrentInstance = () => currentInstance;2916const setCurrentInstance = (instance) => {2917 currentInstance = instance;2918};2919const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component');2920function validateComponentName(name, config) {2921 const appIsNativeTag = config.isNativeTag || NO;2922 if (isBuiltInTag(name) || appIsNativeTag(name)) {2923 warn('Do not use built-in or reserved HTML elements as component id: ' + name);2924 }2925}2926function setupStatefulComponent(instance, parentSuspense) {2927 const Component = instance.type;2928 if (process.env.NODE_ENV !== 'production') {2929 if (Component.name) {2930 validateComponentName(Component.name, instance.appContext.config);2931 }2932 if (Component.components) {2933 const names = Object.keys(Component.components);2934 for (let i = 0; i < names.length; i++) {2935 const name = names[i];2936 validateComponentName(name, instance.appContext.config);2937 }2938 }2939 if (Component.directives) {2940 const names = Object.keys(Component.directives);2941 for (let i = 0; i < names.length; i++) {2942 validateDirectiveName(names[i]);2943 }2944 }2945 }2946 // 0. create render proxy property access cache2947 instance.accessCache = {};2948 // 1. create render proxy2949 instance.renderProxy = new Proxy(instance, PublicInstanceProxyHandlers);2950 // 2. create props proxy2951 // the propsProxy is a reactive AND readonly proxy to the actual props.2952 // it will be updated in resolveProps() on updates before render2953 const propsProxy = (instance.propsProxy = readonly(instance.props));2954 // 3. call setup()2955 const { setup } = Component;2956 if (setup) {
...
runtime-core.cjs.js
Source:runtime-core.cjs.js
...1045])1046*/1047const valueCache = new WeakMap();1048const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text');1049function validateDirectiveName(name) {1050 if (isBuiltInDirective(name)) {1051 warn('Do not use built-in directive ids as custom directive id: ' + name);1052 }1053}1054function applyDirective(props, instance, directive, value, arg, modifiers = EMPTY_OBJ) {1055 let valueCacheForDir = valueCache.get(directive);1056 if (!valueCacheForDir) {1057 valueCacheForDir = new WeakMap();1058 valueCache.set(directive, valueCacheForDir);1059 }1060 if (isFunction(directive)) {1061 directive = {1062 mounted: directive,1063 updated: directive1064 };1065 }1066 for (const key in directive) {1067 const hook = directive[key];1068 const hookKey = `onVnode` + key[0].toUpperCase() + key.slice(1);1069 const vnodeHook = (vnode, prevVNode) => {1070 let oldValue;1071 if (prevVNode != null) {1072 oldValue = valueCacheForDir.get(prevVNode);1073 valueCacheForDir.delete(prevVNode);1074 }1075 valueCacheForDir.set(vnode, value);1076 hook(vnode.el, {1077 instance: instance.renderProxy,1078 value,1079 oldValue,1080 arg,1081 modifiers1082 }, vnode, prevVNode);1083 };1084 const existing = props[hookKey];1085 props[hookKey] = existing1086 ? [].concat(existing, vnodeHook)1087 : vnodeHook;1088 }1089}1090function withDirectives(vnode, directives) {1091 const instance = currentRenderingInstance;1092 if (instance !== null) {1093 vnode.props = vnode.props || {};1094 for (let i = 0; i < directives.length; i++) {1095 const [dir, value, arg, modifiers] = directives[i];1096 applyDirective(vnode.props, instance, dir, value, arg, modifiers);1097 }1098 }1099 else {1100 warn(`withDirectives can only be used inside render functions.`);1101 }1102 return vnode;1103}1104function invokeDirectiveHook(hook, instance, vnode, prevVNode = null) {1105 callWithAsyncErrorHandling(hook, instance, 7 /* DIRECTIVE_HOOK */, [1106 vnode,1107 prevVNode1108 ]);1109}1110function createAppContext() {1111 return {1112 config: {1113 devtools: true,1114 performance: false,1115 isNativeTag: NO,1116 isCustomElement: NO,1117 errorHandler: undefined,1118 warnHandler: undefined1119 },1120 mixins: [],1121 components: {},1122 directives: {},1123 provides: {}1124 };1125}1126function createAppAPI(render) {1127 return function createApp() {1128 const context = createAppContext();1129 let isMounted = false;1130 const app = {1131 get config() {1132 return context.config;1133 },1134 set config(v) {1135 {1136 warn(`app.config cannot be replaced. Modify individual options instead.`);1137 }1138 },1139 use(plugin) {1140 if (isFunction(plugin)) {1141 plugin(app);1142 }1143 else if (isFunction(plugin.install)) {1144 plugin.install(app);1145 }1146 else {1147 warn(`A plugin must either be a function or an object with an "install" ` +1148 `function.`);1149 }1150 return app;1151 },1152 mixin(mixin) {1153 context.mixins.push(mixin);1154 return app;1155 },1156 component(name, component) {1157 {1158 validateComponentName(name, context.config);1159 }1160 if (!component) {1161 return context.components[name];1162 }1163 else {1164 context.components[name] = component;1165 return app;1166 }1167 },1168 directive(name, directive) {1169 {1170 validateDirectiveName(name);1171 }1172 if (!directive) {1173 return context.directives[name];1174 }1175 else {1176 context.directives[name] = directive;1177 return app;1178 }1179 },1180 mount(rootComponent, rootContainer, rootProps) {1181 if (!isMounted) {1182 const vnode = createVNode(rootComponent, rootProps);1183 // store app context on the root VNode.1184 // this will be set on the root instance on initial mount.1185 vnode.appContext = context;1186 render(vnode, rootContainer);1187 isMounted = true;1188 return vnode.component.renderProxy;1189 }1190 else {1191 warn(`App has already been mounted. Create a new app instance instead.`);1192 }1193 },1194 provide(key, value) {1195 if ( key in context.provides) {1196 warn(`App already provides property with key "${key}". ` +1197 `It will be overwritten with the new value.`);1198 }1199 // TypeScript doesn't allow symbols as index type1200 // https://github.com/Microsoft/TypeScript/issues/245871201 context.provides[key] = value;1202 }1203 };1204 return app;1205 };1206}1207function createSuspenseBoundary(vnode, parent, parentComponent, container, hiddenContainer, anchor, isSVG, optimized) {1208 return {1209 vnode,1210 parent,1211 parentComponent,1212 isSVG,1213 optimized,1214 container,1215 hiddenContainer,1216 anchor,1217 deps: 0,1218 subTree: null,1219 fallbackTree: null,1220 isResolved: false,1221 isUnmounted: false,1222 effects: []1223 };1224}1225function normalizeSuspenseChildren(vnode) {1226 const { shapeFlag, children } = vnode;1227 if (shapeFlag & PublicShapeFlags.SLOTS_CHILDREN) {1228 const { default: d, fallback } = children;1229 return {1230 content: normalizeVNode(isFunction(d) ? d() : d),1231 fallback: normalizeVNode(isFunction(fallback) ? fallback() : fallback)1232 };1233 }1234 else {1235 return {1236 content: normalizeVNode(children),1237 fallback: normalizeVNode(null)1238 };1239 }1240}1241function createDevEffectOptions(instance) {1242 return {1243 scheduler: queueJob,1244 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1245 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01246 };1247}1248function isSameType$1(n1, n2) {1249 return n1.type === n2.type && n1.key === n2.key;1250}1251function invokeHooks(hooks, arg) {1252 for (let i = 0; i < hooks.length; i++) {1253 hooks[i](arg);1254 }1255}1256function queuePostRenderEffect(fn, suspense) {1257 if (suspense !== null && !suspense.isResolved) {1258 if (isArray(fn)) {1259 suspense.effects.push(...fn);1260 }1261 else {1262 suspense.effects.push(fn);1263 }1264 }1265 else {1266 queuePostFlushCb(fn);1267 }1268}1269/**1270 * The createRenderer function accepts two generic arguments:1271 * HostNode and HostElement, corresponding to Node and Element types in the1272 * host environment. For example, for runtime-dom, HostNode would be the DOM1273 * `Node` interface and HostElement would be the DOM `Element` interface.1274 *1275 * Custom renderers can pass in the platform specific types like this:1276 *1277 * ``` js1278 * const { render, createApp } = createRenderer<Node, Element>({1279 * patchProp,1280 * ...nodeOps1281 * })1282 * ```1283 */1284function createRenderer(options) {1285 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1286 function patch(n1, // null means this is a mount1287 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1288 // patching & not same type, unmount old tree1289 if (n1 != null) {1290 if (!isSameType$1(n1, n2)) {1291 anchor = getNextHostNode(n1);1292 unmount(n1, parentComponent, parentSuspense, true);1293 n1 = null;1294 }1295 else if (n1.props && n1.props.$once) {1296 return;1297 }1298 }1299 const { type, shapeFlag } = n2;1300 switch (type) {1301 case Text:1302 processText(n1, n2, container, anchor);1303 break;1304 case Comment:1305 processCommentNode(n1, n2, container, anchor);1306 break;1307 case Fragment:1308 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1309 break;1310 case Portal:1311 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1312 break;1313 case Suspense:1314 {1315 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1316 }1317 break;1318 default:1319 if (shapeFlag & 1 /* ELEMENT */) {1320 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1321 }1322 else if (shapeFlag & 6 /* COMPONENT */) {1323 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1324 }1325 else {1326 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1327 }1328 }1329 }1330 function processText(n1, n2, container, anchor) {1331 if (n1 == null) {1332 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1333 }1334 else {1335 const el = (n2.el = n1.el);1336 if (n2.children !== n1.children) {1337 hostSetText(el, n2.children);1338 }1339 }1340 }1341 function processCommentNode(n1, n2, container, anchor) {1342 if (n1 == null) {1343 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1344 }1345 else {1346 // there's no support for dynamic comments1347 n2.el = n1.el;1348 }1349 }1350 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1351 if (n1 == null) {1352 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1353 }1354 else {1355 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1356 }1357 if (n2.ref !== null && parentComponent !== null) {1358 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1359 }1360 }1361 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1362 const tag = vnode.type;1363 isSVG = isSVG || tag === 'svg';1364 const el = (vnode.el = hostCreateElement(tag, isSVG));1365 const { props, shapeFlag } = vnode;1366 if (props != null) {1367 for (const key in props) {1368 if (isReservedProp(key))1369 continue;1370 hostPatchProp(el, key, props[key], null, isSVG);1371 }1372 if (props.onVnodeBeforeMount != null) {1373 invokeDirectiveHook(props.onVnodeBeforeMount, parentComponent, vnode);1374 }1375 }1376 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1377 hostSetElementText(el, vnode.children);1378 }1379 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1380 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG, optimized || vnode.dynamicChildren !== null);1381 }1382 hostInsert(el, container, anchor);1383 if (props != null && props.onVnodeMounted != null) {1384 queuePostRenderEffect(() => {1385 invokeDirectiveHook(props.onVnodeMounted, parentComponent, vnode);1386 }, parentSuspense);1387 }1388 }1389 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) {1390 for (let i = start; i < children.length; i++) {1391 const child = optimized1392 ? children[i]1393 : (children[i] = normalizeVNode(children[i]));1394 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1395 }1396 }1397 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {1398 const el = (n2.el = n1.el);1399 const { patchFlag, dynamicChildren } = n2;1400 const oldProps = (n1 && n1.props) || EMPTY_OBJ;1401 const newProps = n2.props || EMPTY_OBJ;1402 if (newProps.onVnodeBeforeUpdate != null) {1403 invokeDirectiveHook(newProps.onVnodeBeforeUpdate, parentComponent, n2, n1);1404 }1405 if (patchFlag > 0) {1406 // the presence of a patchFlag means this element's render code was1407 // generated by the compiler and can take the fast path.1408 // in this path old node and new node are guaranteed to have the same shape1409 // (i.e. at the exact same position in the source template)1410 if (patchFlag & 16 /* FULL_PROPS */) {1411 // element props contain dynamic keys, full diff needed1412 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1413 }1414 else {1415 // class1416 // this flag is matched when the element has dynamic class bindings.1417 if (patchFlag & 2 /* CLASS */) {1418 if (oldProps.class !== newProps.class) {1419 hostPatchProp(el, 'class', newProps.class, null, isSVG);1420 }1421 }1422 // style1423 // this flag is matched when the element has dynamic style bindings1424 if (patchFlag & 4 /* STYLE */) {1425 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);1426 }1427 // props1428 // This flag is matched when the element has dynamic prop/attr bindings1429 // other than class and style. The keys of dynamic prop/attrs are saved for1430 // faster iteration.1431 // Note dynamic keys like :[foo]="bar" will cause this optimization to1432 // bail out and go through a full diff because we need to unset the old key1433 if (patchFlag & 8 /* PROPS */) {1434 // if the flag is present then dynamicProps must be non-null1435 const propsToUpdate = n2.dynamicProps;1436 for (let i = 0; i < propsToUpdate.length; i++) {1437 const key = propsToUpdate[i];1438 const prev = oldProps[key];1439 const next = newProps[key];1440 if (prev !== next) {1441 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);1442 }1443 }1444 }1445 }1446 // text1447 // This flag is matched when the element has only dynamic text children.1448 // this flag is terminal (i.e. skips children diffing).1449 if (patchFlag & 1 /* TEXT */) {1450 if (n1.children !== n2.children) {1451 hostSetElementText(el, n2.children);1452 }1453 return; // terminal1454 }1455 }1456 else if (!optimized && dynamicChildren == null) {1457 // unoptimized, full diff1458 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1459 }1460 if (dynamicChildren != null) {1461 patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, isSVG);1462 }1463 else if (!optimized) {1464 // full diff1465 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);1466 }1467 if (newProps.onVnodeUpdated != null) {1468 queuePostRenderEffect(() => {1469 invokeDirectiveHook(newProps.onVnodeUpdated, parentComponent, n2, n1);1470 }, parentSuspense);1471 }1472 }1473 // The fast path for blocks.1474 function patchBlockChildren(oldChildren, newChildren, fallbackContainer, parentComponent, parentSuspense, isSVG) {1475 for (let i = 0; i < newChildren.length; i++) {1476 const oldVNode = oldChildren[i];1477 patch(oldVNode, newChildren[i], 1478 // in the case of a Fragment, we need to provide the actual parent1479 // of the Fragment itself so it can move its children. In other cases,1480 // the parent container is not actually used so we just pass the1481 // block element here to avoid a DOM parentNode call.1482 oldVNode.type === Fragment1483 ? hostParentNode(oldVNode.el)1484 : fallbackContainer, null, parentComponent, parentSuspense, isSVG, true);1485 }1486 }1487 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {1488 if (oldProps !== newProps) {1489 for (const key in newProps) {1490 if (isReservedProp(key))1491 continue;1492 const next = newProps[key];1493 const prev = oldProps[key];1494 if (next !== prev) {1495 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1496 }1497 }1498 if (oldProps !== EMPTY_OBJ) {1499 for (const key in oldProps) {1500 if (isReservedProp(key))1501 continue;1502 if (!(key in newProps)) {1503 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1504 }1505 }1506 }1507 }1508 }1509 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1510 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));1511 const fragmentEndAnchor = (n2.anchor = n11512 ? n1.anchor1513 : hostCreateComment(''));1514 if (n1 == null) {1515 hostInsert(fragmentStartAnchor, container, anchor);1516 hostInsert(fragmentEndAnchor, container, anchor);1517 // a fragment can only have array children1518 // since they are either generated by the compiler, or implicitly created1519 // from arrays.1520 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);1521 }1522 else {1523 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);1524 }1525 }1526 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1527 const targetSelector = n2.props && n2.props.target;1528 const { patchFlag, shapeFlag, children } = n2;1529 if (n1 == null) {1530 const target = (n2.target = isString(targetSelector)1531 ? hostQuerySelector(targetSelector)1532 : null);1533 if (target != null) {1534 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1535 hostSetElementText(target, children);1536 }1537 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1538 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG, optimized);1539 }1540 }1541 else {1542 warn('Invalid Portal target on mount:', target, `(${typeof target})`);1543 }1544 }1545 else {1546 // update content1547 const target = (n2.target = n1.target);1548 if (patchFlag === 1 /* TEXT */) {1549 hostSetElementText(target, children);1550 }1551 else if (n2.dynamicChildren) {1552 // fast path when the portal happens to be a block root1553 patchBlockChildren(n1.dynamicChildren, n2.dynamicChildren, container, parentComponent, parentSuspense, isSVG);1554 }1555 else if (!optimized) {1556 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);1557 }1558 // target changed1559 if (targetSelector !== (n1.props && n1.props.target)) {1560 const nextTarget = (n2.target = isString(targetSelector)1561 ? hostQuerySelector(targetSelector)1562 : null);1563 if (nextTarget != null) {1564 // move content1565 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1566 hostSetElementText(target, '');1567 hostSetElementText(nextTarget, children);1568 }1569 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1570 for (let i = 0; i < children.length; i++) {1571 move(children[i], nextTarget, null);1572 }1573 }1574 }1575 else {1576 warn('Invalid Portal target on update:', target, `(${typeof target})`);1577 }1578 }1579 }1580 // insert an empty node as the placeholder for the portal1581 processCommentNode(n1, n2, container, anchor);1582 }1583 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1584 if (n1 == null) {1585 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1586 }1587 else {1588 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);1589 }1590 }1591 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1592 const hiddenContainer = hostCreateElement('div');1593 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));1594 const { content, fallback } = normalizeSuspenseChildren(n2);1595 suspense.subTree = content;1596 suspense.fallbackTree = fallback;1597 // start mounting the content subtree in an off-dom container1598 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1599 // now check if we have encountered any async deps1600 if (suspense.deps > 0) {1601 // mount the fallback tree1602 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1603 isSVG, optimized);1604 n2.el = fallback.el;1605 }1606 else {1607 // Suspense has no async deps. Just resolve.1608 resolveSuspense(suspense);1609 }1610 }1611 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {1612 const suspense = (n2.suspense = n1.suspense);1613 suspense.vnode = n2;1614 const { content, fallback } = normalizeSuspenseChildren(n2);1615 const oldSubTree = suspense.subTree;1616 const oldFallbackTree = suspense.fallbackTree;1617 if (!suspense.isResolved) {1618 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1619 if (suspense.deps > 0) {1620 // still pending. patch the fallback tree.1621 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1622 isSVG, optimized);1623 n2.el = fallback.el;1624 }1625 // If deps somehow becomes 0 after the patch it means the patch caused an1626 // async dep component to unmount and removed its dep. It will cause the1627 // suspense to resolve and we don't need to do anything here.1628 }1629 else {1630 // just normal patch inner content as a fragment1631 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);1632 n2.el = content.el;1633 }1634 suspense.subTree = content;1635 suspense.fallbackTree = fallback;1636 }1637 function resolveSuspense(suspense) {1638 {1639 if (suspense.isResolved) {1640 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);1641 }1642 if (suspense.isUnmounted) {1643 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);1644 }1645 }1646 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;1647 // this is initial anchor on mount1648 let { anchor } = suspense;1649 // unmount fallback tree1650 if (fallbackTree.el) {1651 // if the fallback tree was mounted, it may have been moved1652 // as part of a parent suspense. get the latest anchor for insertion1653 anchor = getNextHostNode(fallbackTree);1654 unmount(fallbackTree, parentComponent, suspense, true);1655 }1656 // move content from off-dom container to actual container1657 move(subTree, container, anchor);1658 const el = (vnode.el = subTree.el);1659 // suspense as the root node of a component...1660 if (parentComponent && parentComponent.subTree === vnode) {1661 parentComponent.vnode.el = el;1662 updateHOCHostEl(parentComponent, el);1663 }1664 // check if there is a pending parent suspense1665 let parent = suspense.parent;1666 let hasUnresolvedAncestor = false;1667 while (parent) {1668 if (!parent.isResolved) {1669 // found a pending parent suspense, merge buffered post jobs1670 // into that parent1671 parent.effects.push(...effects);1672 hasUnresolvedAncestor = true;1673 break;1674 }1675 parent = parent.parent;1676 }1677 // no pending parent suspense, flush all jobs1678 if (!hasUnresolvedAncestor) {1679 queuePostFlushCb(effects);1680 }1681 suspense.isResolved = true;1682 // invoke @resolve event1683 const onResolve = vnode.props && vnode.props.onResolve;1684 if (isFunction(onResolve)) {1685 onResolve();1686 }1687 }1688 function restartSuspense(suspense) {1689 suspense.isResolved = false;1690 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;1691 // move content tree back to the off-dom container1692 const anchor = getNextHostNode(subTree);1693 move(subTree, hiddenContainer, null);1694 // remount the fallback tree1695 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context1696 isSVG, optimized);1697 const el = (vnode.el = fallbackTree.el);1698 // suspense as the root node of a component...1699 if (parentComponent && parentComponent.subTree === vnode) {1700 parentComponent.vnode.el = el;1701 updateHOCHostEl(parentComponent, el);1702 }1703 // invoke @suspense event1704 const onSuspense = vnode.props && vnode.props.onSuspense;1705 if (isFunction(onSuspense)) {1706 onSuspense();1707 }1708 }1709 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1710 if (n1 == null) {1711 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);1712 }1713 else {1714 const instance = (n2.component = n1.component);1715 if (shouldUpdateComponent(n1, n2, optimized)) {1716 if (1717 instance.asyncDep &&1718 !instance.asyncResolved) {1719 // async & still pending - just update props and slots1720 // since the component's reactive effect for render isn't set-up yet1721 {1722 pushWarningContext(n2);1723 }1724 updateComponentPreRender(instance, n2);1725 {1726 popWarningContext();1727 }1728 return;1729 }1730 else {1731 // normal update1732 instance.next = n2;1733 // instance.update is the reactive effect runner.1734 instance.update();1735 }1736 }1737 else {1738 // no update needed. just copy over properties1739 n2.component = n1.component;1740 n2.el = n1.el;1741 }1742 }1743 if (n2.ref !== null && parentComponent !== null) {1744 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);1745 }1746 }1747 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {1748 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));1749 {1750 pushWarningContext(initialVNode);1751 }1752 // resolve props and slots for setup context1753 const propsOptions = initialVNode.type.props;1754 resolveProps(instance, initialVNode.props, propsOptions);1755 resolveSlots(instance, initialVNode.children);1756 // setup stateful logic1757 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {1758 setupStatefulComponent(instance, parentSuspense);1759 }1760 // setup() is async. This component relies on async logic to be resolved1761 // before proceeding1762 if ( instance.asyncDep) {1763 if (!parentSuspense) {1764 // TODO handle this properly1765 throw new Error('Async component without a suspense boundary!');1766 }1767 // parent suspense already resolved, need to re-suspense1768 // use queueJob so it's handled synchronously after patching the current1769 // suspense tree1770 if (parentSuspense.isResolved) {1771 queueJob(() => {1772 restartSuspense(parentSuspense);1773 });1774 }1775 parentSuspense.deps++;1776 instance.asyncDep1777 .catch(err => {1778 handleError(err, instance, 0 /* SETUP_FUNCTION */);1779 })1780 .then(asyncSetupResult => {1781 // component may be unmounted before resolve1782 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {1783 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);1784 }1785 });1786 // give it a placeholder1787 const placeholder = (instance.subTree = createVNode(Comment));1788 processCommentNode(null, placeholder, container, anchor);1789 initialVNode.el = placeholder.el;1790 return;1791 }1792 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);1793 {1794 popWarningContext();1795 }1796 }1797 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {1798 parentSuspense.deps--;1799 // retry from this component1800 instance.asyncResolved = true;1801 const { vnode } = instance;1802 {1803 pushWarningContext(vnode);1804 }1805 handleSetupResult(instance, asyncSetupResult, parentSuspense);1806 setupRenderEffect(instance, parentSuspense, vnode, 1807 // component may have been moved before resolve1808 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);1809 updateHOCHostEl(instance, vnode.el);1810 {1811 popWarningContext();1812 }1813 if (parentSuspense.deps === 0) {1814 resolveSuspense(parentSuspense);1815 }1816 }1817 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {1818 // create reactive effect for rendering1819 let mounted = false;1820 instance.update = reactivity.effect(function componentEffect() {1821 if (!mounted) {1822 const subTree = (instance.subTree = renderComponentRoot(instance));1823 // beforeMount hook1824 if (instance.bm !== null) {1825 invokeHooks(instance.bm);1826 }1827 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);1828 initialVNode.el = subTree.el;1829 // mounted hook1830 if (instance.m !== null) {1831 queuePostRenderEffect(instance.m, parentSuspense);1832 }1833 mounted = true;1834 }1835 else {1836 // updateComponent1837 // This is triggered by mutation of component's own state (next: null)1838 // OR parent calling processComponent (next: HostVNode)1839 const { next } = instance;1840 {1841 pushWarningContext(next || instance.vnode);1842 }1843 if (next !== null) {1844 updateComponentPreRender(instance, next);1845 }1846 const prevTree = instance.subTree;1847 const nextTree = (instance.subTree = renderComponentRoot(instance));1848 // beforeUpdate hook1849 if (instance.bu !== null) {1850 invokeHooks(instance.bu);1851 }1852 // reset refs1853 // only needed if previous patch had refs1854 if (instance.refs !== EMPTY_OBJ) {1855 instance.refs = {};1856 }1857 patch(prevTree, nextTree, 1858 // parent may have changed if it's in a portal1859 hostParentNode(prevTree.el), 1860 // anchor may have changed if it's in a fragment1861 getNextHostNode(prevTree), instance, parentSuspense, isSVG);1862 instance.vnode.el = nextTree.el;1863 if (next === null) {1864 // self-triggered update. In case of HOC, update parent component1865 // vnode el. HOC is indicated by parent instance's subTree pointing1866 // to child component's vnode1867 updateHOCHostEl(instance, nextTree.el);1868 }1869 // updated hook1870 if (instance.u !== null) {1871 queuePostRenderEffect(instance.u, parentSuspense);1872 }1873 {1874 popWarningContext();1875 }1876 }1877 }, createDevEffectOptions(instance) );1878 }1879 function updateComponentPreRender(instance, nextVNode) {1880 nextVNode.component = instance;1881 instance.vnode = nextVNode;1882 instance.next = null;1883 resolveProps(instance, nextVNode.props, nextVNode.type.props);1884 resolveSlots(instance, nextVNode.children);1885 }1886 function updateHOCHostEl({ vnode, parent }, el) {1887 while (parent && parent.subTree === vnode) {1888 (vnode = parent.vnode).el = el;1889 parent = parent.parent;1890 }1891 }1892 function patchChildren(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized = false) {1893 const c1 = n1 && n1.children;1894 const prevShapeFlag = n1 ? n1.shapeFlag : 0;1895 const c2 = n2.children;1896 const { patchFlag, shapeFlag } = n2;1897 if (patchFlag === -1 /* BAIL */) {1898 optimized = false;1899 }1900 // fast path1901 if (patchFlag > 0) {1902 if (patchFlag & 64 /* KEYED_FRAGMENT */) {1903 // this could be either fully-keyed or mixed (some keyed some not)1904 // presence of patchFlag means children are guaranteed to be arrays1905 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1906 return;1907 }1908 else if (patchFlag & 128 /* UNKEYED_FRAGMENT */) {1909 // unkeyed1910 patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1911 return;1912 }1913 }1914 // children has 3 possibilities: text, array or no children.1915 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1916 // text children fast path1917 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {1918 unmountChildren(c1, parentComponent, parentSuspense);1919 }1920 if (c2 !== c1) {1921 hostSetElementText(container, c2);1922 }1923 }1924 else {1925 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {1926 // prev children was array1927 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1928 // two arrays, cannot assume anything, do full diff1929 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1930 }1931 else {1932 // no new children, just unmount old1933 unmountChildren(c1, parentComponent, parentSuspense, true);1934 }1935 }1936 else {1937 // prev children was text OR null1938 // new children is array OR null1939 if (prevShapeFlag & 8 /* TEXT_CHILDREN */) {1940 hostSetElementText(container, '');1941 }1942 // mount new if array1943 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1944 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1945 }1946 }1947 }1948 }1949 function patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1950 c1 = c1 || EMPTY_ARR;1951 c2 = c2 || EMPTY_ARR;1952 const oldLength = c1.length;1953 const newLength = c2.length;1954 const commonLength = Math.min(oldLength, newLength);1955 let i;1956 for (i = 0; i < commonLength; i++) {1957 const nextChild = optimized1958 ? c2[i]1959 : (c2[i] = normalizeVNode(c2[i]));1960 patch(c1[i], nextChild, container, null, parentComponent, parentSuspense, isSVG, optimized);1961 }1962 if (oldLength > newLength) {1963 // remove old1964 unmountChildren(c1, parentComponent, parentSuspense, true, commonLength);1965 }1966 else {1967 // mount new1968 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, commonLength);1969 }1970 }1971 // can be all-keyed or mixed1972 function patchKeyedChildren(c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) {1973 let i = 0;1974 const l2 = c2.length;1975 let e1 = c1.length - 1; // prev ending index1976 let e2 = l2 - 1; // next ending index1977 // 1. sync from start1978 // (a b) c1979 // (a b) d e1980 while (i <= e1 && i <= e2) {1981 const n1 = c1[i];1982 const n2 = optimized1983 ? c2[i]1984 : (c2[i] = normalizeVNode(c2[i]));1985 if (isSameType$1(n1, n2)) {1986 patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);1987 }1988 else {1989 break;1990 }1991 i++;1992 }1993 // 2. sync from end1994 // a (b c)1995 // d e (b c)1996 while (i <= e1 && i <= e2) {1997 const n1 = c1[e1];1998 const n2 = optimized1999 ? c2[i]2000 : (c2[e2] = normalizeVNode(c2[e2]));2001 if (isSameType$1(n1, n2)) {2002 patch(n1, n2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized);2003 }2004 else {2005 break;2006 }2007 e1--;2008 e2--;2009 }2010 // 3. common sequence + mount2011 // (a b)2012 // (a b) c2013 // i = 2, e1 = 1, e2 = 22014 // (a b)2015 // c (a b)2016 // i = 0, e1 = -1, e2 = 02017 if (i > e1) {2018 if (i <= e2) {2019 const nextPos = e2 + 1;2020 const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;2021 while (i <= e2) {2022 patch(null, optimized ? c2[i] : (c2[i] = normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);2023 i++;2024 }2025 }2026 }2027 // 4. common sequence + unmount2028 // (a b) c2029 // (a b)2030 // i = 2, e1 = 2, e2 = 12031 // a (b c)2032 // (b c)2033 // i = 0, e1 = 0, e2 = -12034 else if (i > e2) {2035 while (i <= e1) {2036 unmount(c1[i], parentComponent, parentSuspense, true);2037 i++;2038 }2039 }2040 // 5. unknown sequence2041 // [i ... e1 + 1]: a b [c d e] f g2042 // [i ... e2 + 1]: a b [e d c h] f g2043 // i = 2, e1 = 4, e2 = 52044 else {2045 const s1 = i; // prev starting index2046 const s2 = i; // next starting index2047 // 5.1 build key:index map for newChildren2048 const keyToNewIndexMap = new Map();2049 for (i = s2; i <= e2; i++) {2050 const nextChild = optimized2051 ? c2[i]2052 : (c2[i] = normalizeVNode(c2[i]));2053 if (nextChild.key != null) {2054 if ( keyToNewIndexMap.has(nextChild.key)) {2055 warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);2056 }2057 keyToNewIndexMap.set(nextChild.key, i);2058 }2059 }2060 // 5.2 loop through old children left to be patched and try to patch2061 // matching nodes & remove nodes that are no longer present2062 let j;2063 let patched = 0;2064 const toBePatched = e2 - s2 + 1;2065 let moved = false;2066 // used to track whether any node has moved2067 let maxNewIndexSoFar = 0;2068 // works as Map<newIndex, oldIndex>2069 // Note that oldIndex is offset by +12070 // and oldIndex = 0 is a special value indicating the new node has2071 // no corresponding old node.2072 // used for determining longest stable subsequence2073 const newIndexToOldIndexMap = new Array(toBePatched);2074 for (i = 0; i < toBePatched; i++)2075 newIndexToOldIndexMap[i] = 0;2076 for (i = s1; i <= e1; i++) {2077 const prevChild = c1[i];2078 if (patched >= toBePatched) {2079 // all new children have been patched so this can only be a removal2080 unmount(prevChild, parentComponent, parentSuspense, true);2081 continue;2082 }2083 let newIndex;2084 if (prevChild.key != null) {2085 newIndex = keyToNewIndexMap.get(prevChild.key);2086 }2087 else {2088 // key-less node, try to locate a key-less node of the same type2089 for (j = s2; j <= e2; j++) {2090 if (newIndexToOldIndexMap[j - s2] === 0 &&2091 isSameType$1(prevChild, c2[j])) {2092 newIndex = j;2093 break;2094 }2095 }2096 }2097 if (newIndex === undefined) {2098 unmount(prevChild, parentComponent, parentSuspense, true);2099 }2100 else {2101 newIndexToOldIndexMap[newIndex - s2] = i + 1;2102 if (newIndex >= maxNewIndexSoFar) {2103 maxNewIndexSoFar = newIndex;2104 }2105 else {2106 moved = true;2107 }2108 patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);2109 patched++;2110 }2111 }2112 // 5.3 move and mount2113 // generate longest stable subsequence only when nodes have moved2114 const increasingNewIndexSequence = moved2115 ? getSequence(newIndexToOldIndexMap)2116 : EMPTY_ARR;2117 j = increasingNewIndexSequence.length - 1;2118 // looping backwards so that we can use last patched node as anchor2119 for (i = toBePatched - 1; i >= 0; i--) {2120 const nextIndex = s2 + i;2121 const nextChild = c2[nextIndex];2122 const anchor = nextIndex + 1 < l22123 ? c2[nextIndex + 1].el2124 : parentAnchor;2125 if (newIndexToOldIndexMap[i] === 0) {2126 // mount new2127 patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);2128 }2129 else if (moved) {2130 // move if:2131 // There is no stable subsequence (e.g. a reverse)2132 // OR current node is not among the stable sequence2133 if (j < 0 || i !== increasingNewIndexSequence[j]) {2134 move(nextChild, container, anchor);2135 }2136 else {2137 j--;2138 }2139 }2140 }2141 }2142 }2143 function move(vnode, container, anchor) {2144 if (vnode.component !== null) {2145 move(vnode.component.subTree, container, anchor);2146 return;2147 }2148 if ( vnode.type === Suspense) {2149 const suspense = vnode.suspense;2150 move(suspense.isResolved ? suspense.subTree : suspense.fallbackTree, container, anchor);2151 suspense.container = container;2152 return;2153 }2154 if (vnode.type === Fragment) {2155 hostInsert(vnode.el, container, anchor);2156 const children = vnode.children;2157 for (let i = 0; i < children.length; i++) {2158 move(children[i], container, anchor);2159 }2160 hostInsert(vnode.anchor, container, anchor);2161 }2162 else {2163 hostInsert(vnode.el, container, anchor);2164 }2165 }2166 function unmount(vnode, parentComponent, parentSuspense, doRemove) {2167 const { props, ref, type, component, suspense, children, dynamicChildren, shapeFlag, anchor } = vnode;2168 // unset ref2169 if (ref !== null && parentComponent !== null) {2170 setRef(ref, null, parentComponent, null);2171 }2172 if (component != null) {2173 unmountComponent(component, parentSuspense, doRemove);2174 return;2175 }2176 if ( suspense != null) {2177 unmountSuspense(suspense, parentComponent, parentSuspense, doRemove);2178 return;2179 }2180 if (props != null && props.onVnodeBeforeUnmount != null) {2181 invokeDirectiveHook(props.onVnodeBeforeUnmount, parentComponent, vnode);2182 }2183 const shouldRemoveChildren = type === Fragment && doRemove;2184 if (dynamicChildren != null) {2185 unmountChildren(dynamicChildren, parentComponent, parentSuspense, shouldRemoveChildren);2186 }2187 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2188 unmountChildren(children, parentComponent, parentSuspense, shouldRemoveChildren);2189 }2190 if (doRemove) {2191 hostRemove(vnode.el);2192 if (anchor != null)2193 hostRemove(anchor);2194 }2195 if (props != null && props.onVnodeUnmounted != null) {2196 queuePostRenderEffect(() => {2197 invokeDirectiveHook(props.onVnodeUnmounted, parentComponent, vnode);2198 }, parentSuspense);2199 }2200 }2201 function unmountComponent(instance, parentSuspense, doRemove) {2202 const { bum, effects, update, subTree, um } = instance;2203 // beforeUnmount hook2204 if (bum !== null) {2205 invokeHooks(bum);2206 }2207 if (effects !== null) {2208 for (let i = 0; i < effects.length; i++) {2209 reactivity.stop(effects[i]);2210 }2211 }2212 // update may be null if a component is unmounted before its async2213 // setup has resolved.2214 if (update !== null) {2215 reactivity.stop(update);2216 unmount(subTree, instance, parentSuspense, doRemove);2217 }2218 // unmounted hook2219 if (um !== null) {2220 queuePostRenderEffect(um, parentSuspense);2221 }2222 queuePostFlushCb(() => {2223 instance.isUnmounted = true;2224 });2225 // A component with async dep inside a pending suspense is unmounted before2226 // its async dep resolves. This should remove the dep from the suspense, and2227 // cause the suspense to resolve immediately if that was the last dep.2228 if (2229 parentSuspense !== null &&2230 !parentSuspense.isResolved &&2231 !parentSuspense.isUnmounted &&2232 instance.asyncDep !== null &&2233 !instance.asyncResolved) {2234 parentSuspense.deps--;2235 if (parentSuspense.deps === 0) {2236 resolveSuspense(parentSuspense);2237 }2238 }2239 }2240 function unmountSuspense(suspense, parentComponent, parentSuspense, doRemove) {2241 suspense.isUnmounted = true;2242 unmount(suspense.subTree, parentComponent, parentSuspense, doRemove);2243 if (!suspense.isResolved) {2244 unmount(suspense.fallbackTree, parentComponent, parentSuspense, doRemove);2245 }2246 }2247 function unmountChildren(children, parentComponent, parentSuspense, doRemove, start = 0) {2248 for (let i = start; i < children.length; i++) {2249 unmount(children[i], parentComponent, parentSuspense, doRemove);2250 }2251 }2252 function getNextHostNode({ component, suspense, anchor, el }) {2253 if (component !== null) {2254 return getNextHostNode(component.subTree);2255 }2256 if ( suspense !== null) {2257 return getNextHostNode(suspense.isResolved ? suspense.subTree : suspense.fallbackTree);2258 }2259 return hostNextSibling((anchor || el));2260 }2261 function setRef(ref, oldRef, parent, value) {2262 const refs = parent.refs === EMPTY_OBJ ? (parent.refs = {}) : parent.refs;2263 const renderContext = reactivity.toRaw(parent.renderContext);2264 // unset old ref2265 if (oldRef !== null && oldRef !== ref) {2266 if (isString(oldRef)) {2267 refs[oldRef] = null;2268 const oldSetupRef = renderContext[oldRef];2269 if (reactivity.isRef(oldSetupRef)) {2270 oldSetupRef.value = null;2271 }2272 }2273 else if (reactivity.isRef(oldRef)) {2274 oldRef.value = null;2275 }2276 }2277 if (isString(ref)) {2278 const setupRef = renderContext[ref];2279 if (reactivity.isRef(setupRef)) {2280 setupRef.value = value;2281 }2282 refs[ref] = value;2283 }2284 else if (reactivity.isRef(ref)) {2285 ref.value = value;2286 }2287 else if (isFunction(ref)) {2288 ref(value, refs);2289 }2290 else {2291 warn('Invalid template ref type:', value, `(${typeof value})`);2292 }2293 }2294 function render(vnode, rawContainer) {2295 let container = rawContainer;2296 if (isString(container)) {2297 container = hostQuerySelector(container);2298 if (!container) {2299 {2300 warn(`Failed to locate root container: ` + `querySelector returned null.`);2301 }2302 return;2303 }2304 }2305 if (vnode == null) {2306 if (container._vnode) {2307 unmount(container._vnode, null, null, true);2308 }2309 }2310 else {2311 patch(container._vnode || null, vnode, container);2312 }2313 flushPostFlushCbs();2314 container._vnode = vnode;2315 }2316 return {2317 render,2318 createApp: createAppAPI(render)2319 };2320}2321// https://en.wikipedia.org/wiki/Longest_increasing_subsequence2322function getSequence(arr) {2323 const p = arr.slice();2324 const result = [0];2325 let i, j, u, v, c;2326 const len = arr.length;2327 for (i = 0; i < len; i++) {2328 const arrI = arr[i];2329 if (arrI !== 0) {2330 j = result[result.length - 1];2331 if (arr[j] < arrI) {2332 p[i] = j;2333 result.push(i);2334 continue;2335 }2336 u = 0;2337 v = result.length - 1;2338 while (u < v) {2339 c = ((u + v) / 2) | 0;2340 if (arr[result[c]] < arrI) {2341 u = c + 1;2342 }2343 else {2344 v = c;2345 }2346 }2347 if (arrI < arr[result[u]]) {2348 if (u > 0) {2349 p[i] = result[u - 1];2350 }2351 result[u] = i;2352 }2353 }2354 }2355 u = result.length;2356 v = result[u - 1];2357 while (u-- > 0) {2358 result[u] = v;2359 v = p[v];2360 }2361 return result;2362}2363const invoke = (fn) => fn();2364// implementation2365function watch(effectOrSource, cbOrOptions, options) {2366 if (isFunction(cbOrOptions)) {2367 // effect callback as 2nd argument - this is a source watcher2368 return doWatch(effectOrSource, cbOrOptions, options);2369 }2370 else {2371 // 2nd argument is either missing or an options object2372 // - this is a simple effect watcher2373 return doWatch(effectOrSource, null, cbOrOptions);2374 }2375}2376function doWatch(source, cb, { lazy, deep, flush, onTrack, onTrigger } = EMPTY_OBJ) {2377 const instance = currentInstance;2378 const suspense = currentSuspense;2379 let getter;2380 if (isArray(source)) {2381 getter = () => source.map(s => reactivity.isRef(s)2382 ? s.value2383 : callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */));2384 }2385 else if (reactivity.isRef(source)) {2386 getter = () => source.value;2387 }2388 else if (cb) {2389 // getter with cb2390 getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */);2391 }2392 else {2393 // no cb -> simple effect2394 getter = () => {2395 if (instance && instance.isUnmounted) {2396 return;2397 }2398 if (cleanup) {2399 cleanup();2400 }2401 return callWithErrorHandling(source, instance, 3 /* WATCH_CALLBACK */, [registerCleanup]);2402 };2403 }2404 if (deep) {2405 const baseGetter = getter;2406 getter = () => traverse(baseGetter());2407 }2408 let cleanup;2409 const registerCleanup = (fn) => {2410 // TODO wrap the cleanup fn for error handling2411 cleanup = runner.onStop = () => {2412 callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */);2413 };2414 };2415 let oldValue = isArray(source) ? [] : undefined;2416 const applyCb = cb2417 ? () => {2418 if (instance && instance.isUnmounted) {2419 return;2420 }2421 const newValue = runner();2422 if (deep || newValue !== oldValue) {2423 // cleanup before running cb again2424 if (cleanup) {2425 cleanup();2426 }2427 callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [2428 newValue,2429 oldValue,2430 registerCleanup2431 ]);2432 oldValue = newValue;2433 }2434 }2435 : void 0;2436 let scheduler;2437 if (flush === 'sync') {2438 scheduler = invoke;2439 }2440 else if (flush === 'pre') {2441 scheduler = job => {2442 if (!instance || instance.vnode.el != null) {2443 queueJob(job);2444 }2445 else {2446 // with 'pre' option, the first call must happen before2447 // the component is mounted so it is called synchronously.2448 job();2449 }2450 };2451 }2452 else {2453 scheduler = job => {2454 queuePostRenderEffect(job, suspense);2455 };2456 }2457 const runner = reactivity.effect(getter, {2458 lazy: true,2459 // so it runs before component update effects in pre flush mode2460 computed: true,2461 onTrack,2462 onTrigger,2463 scheduler: applyCb ? () => scheduler(applyCb) : scheduler2464 });2465 if (!lazy) {2466 if (applyCb) {2467 scheduler(applyCb);2468 }2469 else {2470 scheduler(runner);2471 }2472 }2473 else {2474 oldValue = runner();2475 }2476 recordEffect(runner);2477 return () => {2478 reactivity.stop(runner);2479 };2480}2481// this.$watch2482function instanceWatch(source, cb, options) {2483 const ctx = this.renderProxy;2484 const getter = isString(source) ? () => ctx[source] : source.bind(ctx);2485 const stop = watch(getter, cb.bind(ctx), options);2486 onBeforeUnmount(stop, this);2487 return stop;2488}2489function traverse(value, seen = new Set()) {2490 if (!isObject(value) || seen.has(value)) {2491 return;2492 }2493 seen.add(value);2494 if (isArray(value)) {2495 for (let i = 0; i < value.length; i++) {2496 traverse(value[i], seen);2497 }2498 }2499 else if (value instanceof Map) {2500 value.forEach((v, key) => {2501 // to register mutation dep for existing keys2502 traverse(value.get(key), seen);2503 });2504 }2505 else if (value instanceof Set) {2506 value.forEach(v => {2507 traverse(v, seen);2508 });2509 }2510 else {2511 for (const key in value) {2512 traverse(value[key], seen);2513 }2514 }2515 return value;2516}2517const publicPropertiesMap = {2518 $data: 'data',2519 $props: 'propsProxy',2520 $attrs: 'attrs',2521 $slots: 'slots',2522 $refs: 'refs',2523 $parent: 'parent',2524 $root: 'root',2525 $emit: 'emit',2526 $options: 'type'2527};2528const PublicInstanceProxyHandlers = {2529 get(target, key) {2530 const { renderContext, data, props, propsProxy, accessCache, type } = target;2531 // This getter gets called for every property access on the render context2532 // during render and is a major hotspot. The most expensive part of this2533 // is the multiple hasOwn() calls. It's much faster to do a simple property2534 // access on a plain object, so we use an accessCache object (with null2535 // prototype) to memoize what access type a key corresponds to.2536 const n = accessCache[key];2537 if (n !== undefined) {2538 switch (n) {2539 case 0 /* DATA */:2540 return data[key];2541 case 1 /* CONTEXT */:2542 return renderContext[key];2543 case 2 /* PROPS */:2544 return propsProxy[key];2545 }2546 }2547 else if (data !== EMPTY_OBJ && hasOwn(data, key)) {2548 accessCache[key] = 0 /* DATA */;2549 return data[key];2550 }2551 else if (hasOwn(renderContext, key)) {2552 accessCache[key] = 1 /* CONTEXT */;2553 return renderContext[key];2554 }2555 else if (hasOwn(props, key)) {2556 // only cache props access if component has declared (thus stable) props2557 if (type.props != null) {2558 accessCache[key] = 2 /* PROPS */;2559 }2560 // return the value from propsProxy for ref unwrapping and readonly2561 return propsProxy[key];2562 }2563 else if (key === '$cache') {2564 return target.renderCache || (target.renderCache = []);2565 }2566 else if (key === '$el') {2567 return target.vnode.el;2568 }2569 else if (hasOwn(publicPropertiesMap, key)) {2570 return target[publicPropertiesMap[key]];2571 }2572 // methods are only exposed when options are supported2573 {2574 switch (key) {2575 case '$forceUpdate':2576 return target.update;2577 case '$nextTick':2578 return nextTick;2579 case '$watch':2580 return instanceWatch.bind(target);2581 }2582 }2583 return target.user[key];2584 },2585 set(target, key, value) {2586 const { data, renderContext } = target;2587 if (data !== EMPTY_OBJ && hasOwn(data, key)) {2588 data[key] = value;2589 }2590 else if (hasOwn(renderContext, key)) {2591 renderContext[key] = value;2592 }2593 else if (key[0] === '$' && key.slice(1) in target) {2594 2595 warn(`Attempting to mutate public property "${key}". ` +2596 `Properties starting with $ are reserved and readonly.`, target);2597 return false;2598 }2599 else if (key in target.props) {2600 2601 warn(`Attempting to mutate prop "${key}". Props are readonly.`, target);2602 return false;2603 }2604 else {2605 target.user[key] = value;2606 }2607 return true;2608 }2609};2610function provide(key, value) {2611 if (!currentInstance) {2612 {2613 warn(`provide() can only be used inside setup().`);2614 }2615 }2616 else {2617 let provides = currentInstance.provides;2618 // by default an instance inherits its parent's provides object2619 // but when it needs to provide values of its own, it creates its2620 // own provides object using parent provides object as prototype.2621 // this way in `inject` we can simply look up injections from direct2622 // parent and let the prototype chain do the work.2623 const parentProvides = currentInstance.parent && currentInstance.parent.provides;2624 if (parentProvides === provides) {2625 provides = currentInstance.provides = Object.create(parentProvides);2626 }2627 // TS doesn't allow symbol as index type2628 provides[key] = value;2629 }2630}2631function inject(key, defaultValue) {2632 if (currentInstance) {2633 const provides = currentInstance.provides;2634 if (key in provides) {2635 // TS doesn't allow symbol as index type2636 return provides[key];2637 }2638 else if (defaultValue !== undefined) {2639 return defaultValue;2640 }2641 else {2642 warn(`injection "${key}" not found.`);2643 }2644 }2645 else {2646 warn(`inject() can only be used inside setup().`);2647 }2648}2649function applyOptions(instance, options, asMixin = false) {2650 const renderContext = instance.renderContext === EMPTY_OBJ2651 ? (instance.renderContext = reactivity.reactive({}))2652 : instance.renderContext;2653 const ctx = instance.renderProxy;2654 const { 2655 // composition2656 mixins, extends: extendsOptions, 2657 // state2658 data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions, 2659 // assets2660 components, directives, 2661 // lifecycle2662 beforeMount, mounted, beforeUpdate, updated, 2663 // TODO activated2664 // TODO deactivated2665 beforeUnmount, unmounted, renderTracked, renderTriggered, errorCaptured } = options;2666 const globalMixins = instance.appContext.mixins;2667 // applyOptions is called non-as-mixin once per instance2668 if (!asMixin) {2669 callSyncHook('beforeCreate', options, ctx, globalMixins);2670 // global mixins are applied first2671 applyMixins(instance, globalMixins);2672 }2673 // extending a base component...2674 if (extendsOptions) {2675 applyOptions(instance, extendsOptions, true);2676 }2677 // local mixins2678 if (mixins) {2679 applyMixins(instance, mixins);2680 }2681 // state options2682 if (dataOptions) {2683 const data = isFunction(dataOptions) ? dataOptions.call(ctx) : dataOptions;2684 if (!isObject(data)) {2685 warn(`data() should return an object.`);2686 }2687 else if (instance.data === EMPTY_OBJ) {2688 instance.data = reactivity.reactive(data);2689 }2690 else {2691 // existing data: this is a mixin or extends.2692 extend(instance.data, data);2693 }2694 }2695 if (computedOptions) {2696 for (const key in computedOptions) {2697 const opt = computedOptions[key];2698 if (isFunction(opt)) {2699 renderContext[key] = computed(opt.bind(ctx));2700 }2701 else {2702 const { get, set } = opt;2703 if (isFunction(get)) {2704 renderContext[key] = computed({2705 get: get.bind(ctx),2706 set: isFunction(set)2707 ? set.bind(ctx)2708 : () => {2709 warn(`Computed property "${key}" was assigned to but it has no setter.`);2710 }2711 2712 });2713 }2714 else {2715 warn(`Computed property "${key}" has no getter.`);2716 }2717 }2718 }2719 }2720 if (methods) {2721 for (const key in methods) {2722 renderContext[key] = methods[key].bind(ctx);2723 }2724 }2725 if (watchOptions) {2726 for (const key in watchOptions) {2727 const raw = watchOptions[key];2728 const getter = () => ctx[key];2729 if (isString(raw)) {2730 const handler = renderContext[raw];2731 if (isFunction(handler)) {2732 watch(getter, handler);2733 }2734 else {2735 warn(`Invalid watch handler specified by key "${raw}"`, handler);2736 }2737 }2738 else if (isFunction(raw)) {2739 watch(getter, raw.bind(ctx));2740 }2741 else if (isObject(raw)) {2742 // TODO 2.x compat2743 watch(getter, raw.handler.bind(ctx), raw);2744 }2745 else {2746 warn(`Invalid watch option: "${key}"`);2747 }2748 }2749 }2750 if (provideOptions) {2751 const provides = isFunction(provideOptions)2752 ? provideOptions.call(ctx)2753 : provideOptions;2754 for (const key in provides) {2755 provide(key, provides[key]);2756 }2757 }2758 if (injectOptions) {2759 if (isArray(injectOptions)) {2760 for (let i = 0; i < injectOptions.length; i++) {2761 const key = injectOptions[i];2762 renderContext[key] = inject(key);2763 }2764 }2765 else {2766 for (const key in injectOptions) {2767 const opt = injectOptions[key];2768 if (isObject(opt)) {2769 renderContext[key] = inject(opt.from, opt.default);2770 }2771 else {2772 renderContext[key] = inject(opt);2773 }2774 }2775 }2776 }2777 // asset options2778 if (components) {2779 extend(instance.components, components);2780 }2781 if (directives) {2782 extend(instance.directives, directives);2783 }2784 // lifecycle options2785 if (!asMixin) {2786 callSyncHook('created', options, ctx, globalMixins);2787 }2788 if (beforeMount) {2789 onBeforeMount(beforeMount.bind(ctx));2790 }2791 if (mounted) {2792 onMounted(mounted.bind(ctx));2793 }2794 if (beforeUpdate) {2795 onBeforeUpdate(beforeUpdate.bind(ctx));2796 }2797 if (updated) {2798 onUpdated(updated.bind(ctx));2799 }2800 if (errorCaptured) {2801 onErrorCaptured(errorCaptured.bind(ctx));2802 }2803 if (renderTracked) {2804 onRenderTracked(renderTracked.bind(ctx));2805 }2806 if (renderTriggered) {2807 onRenderTriggered(renderTriggered.bind(ctx));2808 }2809 if (beforeUnmount) {2810 onBeforeUnmount(beforeUnmount.bind(ctx));2811 }2812 if (unmounted) {2813 onUnmounted(unmounted.bind(ctx));2814 }2815}2816function callSyncHook(name, options, ctx, globalMixins) {2817 callHookFromMixins(name, globalMixins, ctx);2818 const baseHook = options.extends && options.extends[name];2819 if (baseHook) {2820 baseHook.call(ctx);2821 }2822 const mixins = options.mixins;2823 if (mixins) {2824 callHookFromMixins(name, mixins, ctx);2825 }2826 const selfHook = options[name];2827 if (selfHook) {2828 selfHook.call(ctx);2829 }2830}2831function callHookFromMixins(name, mixins, ctx) {2832 for (let i = 0; i < mixins.length; i++) {2833 const fn = mixins[i][name];2834 if (fn) {2835 fn.call(ctx);2836 }2837 }2838}2839function applyMixins(instance, mixins) {2840 for (let i = 0; i < mixins.length; i++) {2841 applyOptions(instance, mixins[i], true);2842 }2843}2844const emptyAppContext = createAppContext();2845function createComponentInstance(vnode, parent) {2846 // inherit parent app context - or - if root, adopt from root vnode2847 const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext;2848 const instance = {2849 vnode,2850 parent,2851 appContext,2852 type: vnode.type,2853 root: null,2854 next: null,2855 subTree: null,2856 update: null,2857 render: null,2858 renderProxy: null,2859 propsProxy: null,2860 setupContext: null,2861 effects: null,2862 provides: parent ? parent.provides : Object.create(appContext.provides),2863 accessCache: null,2864 renderCache: null,2865 // setup context properties2866 renderContext: EMPTY_OBJ,2867 data: EMPTY_OBJ,2868 props: EMPTY_OBJ,2869 attrs: EMPTY_OBJ,2870 slots: EMPTY_OBJ,2871 refs: EMPTY_OBJ,2872 // per-instance asset storage (mutable during options resolution)2873 components: Object.create(appContext.components),2874 directives: Object.create(appContext.directives),2875 // async dependency management2876 asyncDep: null,2877 asyncResult: null,2878 asyncResolved: false,2879 // user namespace for storing whatever the user assigns to `this`2880 user: {},2881 // lifecycle hooks2882 // not using enums here because it results in computed properties2883 isUnmounted: false,2884 bc: null,2885 c: null,2886 bm: null,2887 m: null,2888 bu: null,2889 u: null,2890 um: null,2891 bum: null,2892 da: null,2893 a: null,2894 rtg: null,2895 rtc: null,2896 ec: null,2897 emit: (event, ...args) => {2898 const props = instance.vnode.props || EMPTY_OBJ;2899 const handler = props[`on${event}`] || props[`on${capitalize(event)}`];2900 if (handler) {2901 callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args);2902 }2903 }2904 };2905 instance.root = parent ? parent.root : instance;2906 return instance;2907}2908let currentInstance = null;2909let currentSuspense = null;2910const getCurrentInstance = () => currentInstance;2911const setCurrentInstance = (instance) => {2912 currentInstance = instance;2913};2914const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component');2915function validateComponentName(name, config) {2916 const appIsNativeTag = config.isNativeTag || NO;2917 if (isBuiltInTag(name) || appIsNativeTag(name)) {2918 warn('Do not use built-in or reserved HTML elements as component id: ' + name);2919 }2920}2921function setupStatefulComponent(instance, parentSuspense) {2922 const Component = instance.type;2923 {2924 if (Component.name) {2925 validateComponentName(Component.name, instance.appContext.config);2926 }2927 if (Component.components) {2928 const names = Object.keys(Component.components);2929 for (let i = 0; i < names.length; i++) {2930 const name = names[i];2931 validateComponentName(name, instance.appContext.config);2932 }2933 }2934 if (Component.directives) {2935 const names = Object.keys(Component.directives);2936 for (let i = 0; i < names.length; i++) {2937 validateDirectiveName(names[i]);2938 }2939 }2940 }2941 // 0. create render proxy property access cache2942 instance.accessCache = {};2943 // 1. create render proxy2944 instance.renderProxy = new Proxy(instance, PublicInstanceProxyHandlers);2945 // 2. create props proxy2946 // the propsProxy is a reactive AND readonly proxy to the actual props.2947 // it will be updated in resolveProps() on updates before render2948 const propsProxy = (instance.propsProxy = reactivity.readonly(instance.props));2949 // 3. call setup()2950 const { setup } = Component;2951 if (setup) {
...
render.js
Source:render.js
...90 return app;91 },92 directive(name, directive) {93 {94 validateDirectiveName(name);95 }96 if (!directive) {97 return context.directives[name];98 }99 if ( context.directives[name]) {100 warn(`Directive "${name}" has already been registered in target app.`);101 }102 context.directives[name] = directive;103 return app;104 },105 mount(rootContainer, isHydrate) {106 if (!isMounted) {107 const vnode = createVNode(rootComponent, rootProps);108 // store app context on the root VNode.109 // this will be set on the root instance on initial mount.110 vnode.appContext = context;111 // HMR root reload112 {113 context.reload = () => {114 render(cloneVNode(vnode), rootContainer);115 };116 }117 if (isHydrate && hydrate) {118 hydrate(vnode, rootContainer);119 }120 else {121 render(vnode, rootContainer);122 }123 isMounted = true;124 app._container = rootContainer;125 rootContainer.__vue_app__ = app;126 {127 devtoolsInitApp(app, version);128 }129 return vnode.component.proxy;130 }131 else {132 warn(`App has already been mounted.\n` +133 `If you want to remount the same app, move your app creation logic ` +134 `into a factory function and create fresh app instances for each ` +135 `mount - e.g. \`const createMyApp = () => createApp(App)\``);136 }137 },138 unmount() {139 if (isMounted) {140 render(null, app._container);141 {142 devtoolsUnmountApp(app);143 }144 }145 else {146 warn(`Cannot unmount an app that is not mounted.`);147 }148 },149 provide(key, value) {150 if ( key in context.provides) {151 warn(`App already provides property with key "${String(key)}". ` +152 `It will be overwritten with the new value.`);153 }154 // TypeScript doesn't allow symbols as index type155 // https://github.com/Microsoft/TypeScript/issues/24587156 context.provides[key] = value;157 return app;158 }159 });160 return app;161 };162}163function mount(rootContainer, isHydrate) {164 if (!isMounted) {165 const vnode = createVNode(rootComponent, rootProps);166 // store app context on the root VNode.167 // this will be set on the root instance on initial mount.168 vnode.appContext = context;169 // HMR root reload170 {171 context.reload = () => {172 render(cloneVNode(vnode), rootContainer);173 };174 }175 if (isHydrate && hydrate) {176 hydrate(vnode, rootContainer);177 }178 else {179 render(vnode, rootContainer);180 }181 isMounted = true;182 app._container = rootContainer;183 rootContainer.__vue_app__ = app;184 {185 devtoolsInitApp(app, version);186 }187 return vnode.component.proxy;188 }189 else {190 warn(`App has already been mounted.\n` +191 `If you want to remount the same app, move your app creation logic ` +192 `into a factory function and create fresh app instances for each ` +193 `mount - e.g. \`const createMyApp = () => createApp(App)\``);194 }195}196const render = (vnode, container) => {197 if (vnode == null) {198 if (container._vnode) {199 unmount(container._vnode, null, null, true);200 }201 }202 else {203 patch(container._vnode || null, vnode, container);204 }205 flushPostFlushCbs();206 container._vnode = vnode;207};208// 1. createVNode209const createVNode = ( createVNodeWithArgsTransform);210const createVNodeWithArgsTransform = (...args) => {211 return _createVNode(...(vnodeArgsTransformer212 ? vnodeArgsTransformer(args, currentRenderingInstance)213 : args));214};215function _createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, isBlockNode = false) {216 if (!type || type === NULL_DYNAMIC_COMPONENT) {217 if ( !type) {218 warn(`Invalid vnode type when creating vnode: ${type}.`);219 }220 type = Comment;221 }222 if (isVNode(type)) {223 // createVNode receiving an existing vnode. This happens in cases like224 // <component :is="vnode"/>225 // #2078 make sure to merge refs during the clone instead of overwriting it226 const cloned = cloneVNode(type, props, true /* mergeRef: true */);227 if (children) {228 normalizeChildren(cloned, children);229 }230 return cloned;231 }232 // class component normalization.233 if (isClassComponent(type)) {234 type = type.__vccOpts;235 }236 // class & style normalization.237 if (props) {238 // for reactive or proxy objects, we need to clone it to enable mutation.239 if (isProxy(props) || InternalObjectKey in props) {240 props = extend({}, props);241 }242 let { class: klass, style } = props;243 if (klass && !isString(klass)) {244 props.class = normalizeClass(klass);245 }246 if (isObject(style)) {247 // reactive state objects need to be cloned since they are likely to be248 // mutated249 if (isProxy(style) && !isArray(style)) {250 style = extend({}, style);251 }252 props.style = normalizeStyle(style);253 }254 }255 // encode the vnode type information into a bitmap256 const shapeFlag = isString(type)257 ? 1 /* ELEMENT */258 : isSuspense(type)259 ? 128 /* SUSPENSE */260 : isTeleport(type)261 ? 64 /* TELEPORT */262 : isObject(type)263 ? 4 /* STATEFUL_COMPONENT */264 : isFunction(type)265 ? 2 /* FUNCTIONAL_COMPONENT */266 : 0;267 if ( shapeFlag & 4 /* STATEFUL_COMPONENT */ && isProxy(type)) {268 type = toRaw(type);269 warn(`Vue received a Component which was made a reactive object. This can ` +270 `lead to unnecessary performance overhead, and should be avoided by ` +271 `marking the component with \`markRaw\` or using \`shallowRef\` ` +272 `instead of \`ref\`.`, `\nComponent that was made reactive: `, type);273 }274 const vnode = {275 __v_isVNode: true,276 ["__v_skip" /* SKIP */]: true,277 type,278 props,279 key: props && normalizeKey(props),280 ref: props && normalizeRef(props),281 scopeId: currentScopeId,282 children: null,283 component: null,284 suspense: null,285 ssContent: null,286 ssFallback: null,287 dirs: null,288 transition: null,289 el: null,290 anchor: null,291 target: null,292 targetAnchor: null,293 staticCount: 0,294 shapeFlag,295 patchFlag,296 dynamicProps,297 dynamicChildren: null,298 appContext: null299 };300 // validate key301 if ( vnode.key !== vnode.key) {302 warn(`VNode created with invalid key (NaN). VNode type:`, vnode.type);303 }304 normalizeChildren(vnode, children);305 // normalize suspense children306 if ( shapeFlag & 128 /* SUSPENSE */) {307 const { content, fallback } = normalizeSuspenseChildren(vnode);308 vnode.ssContent = content;309 vnode.ssFallback = fallback;310 }311 if (shouldTrack$1 > 0 &&312 // avoid a block node from tracking itself313 !isBlockNode &&314 // has current parent block315 currentBlock &&316 // presence of a patch flag indicates this node needs patching on updates.317 // component nodes also should always be patched, because even if the318 // component doesn't need to update, it needs to persist the instance on to319 // the next vnode so that it can be properly unmounted later.320 (patchFlag > 0 || shapeFlag & 6 /* COMPONENT */) &&321 // the EVENTS flag is only for hydration and if it is the only flag, the322 // vnode should not be considered dynamic due to handler caching.323 patchFlag !== 32 /* HYDRATE_EVENTS */) {324 currentBlock.push(vnode);325 }326 return vnode;327}328function normalizeVNode(child) {329 if (child == null || typeof child === 'boolean') {330 // empty placeholder331 return createVNode(Comment);332 }333 else if (isArray(child)) {334 // fragment335 return createVNode(Fragment, null, child);336 }337 else if (typeof child === 'object') {338 // already vnode, this should be the most common since compiled templates339 // always produce all-vnode children arrays340 return child.el === null ? child : cloneVNode(child);341 }342 else {343 // strings and numbers344 return createVNode(Text, null, String(child));345 }346}347const mountChildren = (children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) => {348 for (let i = start; i < children.length; i++) {349 const child = (children[i] = optimized350 ? cloneIfMounted(children[i])351 : normalizeVNode(children[i]));352 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);353 }354};355const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) => {356 // patching & not same type, unmount old tree357 if (n1 && !isSameVNodeType(n1, n2)) {358 anchor = getNextHostNode(n1);359 unmount(n1, parentComponent, parentSuspense, true);360 n1 = null;361 }362 if (n2.patchFlag === -2 /* BAIL */) {363 optimized = false;364 n2.dynamicChildren = null;365 }366 const { type, ref, shapeFlag } = n2;367 switch (type) {368 case Text:369 processText(n1, n2, container, anchor);370 break;371 case Comment:372 processCommentNode(n1, n2, container, anchor);373 break;374 case Static:375 if (n1 == null) {376 mountStaticNode(n2, container, anchor, isSVG);377 }378 else {379 patchStaticNode(n1, n2, container, isSVG);380 }381 break;382 case Fragment:383 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);384 break;385 default:386 if (shapeFlag & 1 /* ELEMENT */) {387 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);388 }389 else if (shapeFlag & 6 /* COMPONENT */) {390 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);391 }392 else if (shapeFlag & 64 /* TELEPORT */) {393 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);394 }395 else if ( shapeFlag & 128 /* SUSPENSE */) {396 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);397 }398 else {399 warn('Invalid VNode type:', type, `(${typeof type})`);400 }401 }402 // set ref403 if (ref != null && parentComponent) {404 setRef(ref, n1 && n1.ref, parentComponent, parentSuspense, n2);405 }406};407 // const { 408 // insert: hostInsert, 409 // remove: hostRemove, 410 // patchProp: hostPatchProp, 411 // forcePatchProp: hostForcePatchProp, 412 // createElement: hostCreateElement, 413 // createText: hostCreateText, 414 // createComment: hostCreateComment, 415 // setText: hostSetText, 416 // setElementText: hostSetElementText, 417 // parentNode: hostParentNode, 418 // nextSibling: hostNextSibling, 419 // setScopeId: hostSetScopeId = NOOP, 420 // cloneNode: hostCloneNode, 421 // insertStaticContent: hostInsertStaticContent 422 // } = options;423 424 const nodeOps = {425 insert: (child, parent, anchor) => {426 parent.insertBefore(child, anchor || null);427 },428 remove: child => {429 const parent = child.parentNode;430 if (parent) {431 parent.removeChild(child);432 }433 },434 createElement: (tag, isSVG, is) => isSVG435 ? doc.createElementNS(svgNS, tag)436 : doc.createElement(tag, is ? { is } : undefined),437 createText: text => doc.createTextNode(text),438 createComment: text => doc.createComment(text),439 setText: (node, text) => {440 node.nodeValue = text;441 },442 setElementText: (el, text) => {443 el.textContent = text;444 },445 parentNode: node => node.parentNode,446 nextSibling: node => node.nextSibling,447 querySelector: selector => doc.querySelector(selector),448 setScopeId(el, id) {449 el.setAttribute(id, '');450 },451 cloneNode(el) {452 return el.cloneNode(true);453 },454 // __UNSAFE__455 // Reason: innerHTML.456 // Static content here can only come from compiled templates.457 // As long as the user only uses trusted templates, this is safe.458 insertStaticContent(content, parent, anchor, isSVG) {459 const temp = isSVG460 ? tempSVGContainer ||461 (tempSVGContainer = doc.createElementNS(svgNS, 'svg'))462 : tempContainer || (tempContainer = doc.createElement('div'));463 temp.innerHTML = content;464 const first = temp.firstChild;465 let node = first;466 let last = node;467 while (node) {468 last = node;469 nodeOps.insert(node, parent, anchor);470 node = temp.firstChild;471 }472 return [first, last];473 }474 };475 const processText = (n1, n2, container, anchor) => {476 if (n1 == null) {477 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);478 }479 else {480 const el = (n2.el = n1.el);481 if (n2.children !== n1.children) {482 hostSetText(el, n2.children);483 }484 }485 };486 const processCommentNode = (n1, n2, container, anchor) => {487 if (n1 == null) {488 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);489 }490 else {491 // there's no support for dynamic comments492 n2.el = n1.el;493 }494 };495 const mountStaticNode = (n2, container, anchor, isSVG) => {496 [n2.el, n2.anchor] = hostInsertStaticContent(n2.children, container, anchor, isSVG);497 };498 /**499 * Dev / HMR only500 */501 const patchStaticNode = (n1, n2, container, isSVG) => {502 // static nodes are only patched during dev for HMR503 if (n2.children !== n1.children) {504 const anchor = hostNextSibling(n1.anchor);505 // remove existing506 removeStaticNode(n1);507 [n2.el, n2.anchor] = hostInsertStaticContent(n2.children, container, anchor, isSVG);508 }509 else {510 n2.el = n1.el;511 n2.anchor = n1.anchor;512 }513 };514 const removeStaticNode = (vnode) => {515 let cur = vnode.el;516 while (cur && cur !== vnode.anchor) {517 const next = hostNextSibling(cur);518 hostRemove(cur);519 cur = next;520 }521 hostRemove(vnode.anchor);522 };523 // function normalizeVNode(child) {524 // if (child == null || typeof child === 'boolean') {525 // // empty placeholder526 // return createVNode(Comment);527 // }528 // else if (isArray(child)) {529 // // fragment530 // return createVNode(Fragment, null, child);531 // }532 // else if (typeof child === 'object') {533 // // already vnode, this should be the most common since compiled templates534 // // always produce all-vnode children arrays535 // return child.el === null ? child : cloneVNode(child);536 // }537 // else {538 // // strings and numbers539 // return createVNode(Text, null, String(child));540 // }541 // }542 const processFragment = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {543 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''));544 const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''));545 let { patchFlag, dynamicChildren } = n2;546 if (patchFlag > 0) {547 optimized = true;548 }549 if ( isHmrUpdating) {550 // HMR updated, force full diff551 patchFlag = 0;552 optimized = false;553 dynamicChildren = null;554 }555 if (n1 == null) {556 hostInsert(fragmentStartAnchor, container, anchor);557 hostInsert(fragmentEndAnchor, container, anchor);558 // a fragment can only have array children559 // since they are either generated by the compiler, or implicitly created560 // from arrays.561 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);562 }563 else {564 if (patchFlag > 0 &&565 patchFlag & 64 /* STABLE_FRAGMENT */ &&566 dynamicChildren) {567 // a stable fragment (template root or <template v-for>) doesn't need to568 // patch children order, but it may contain dynamicChildren.569 patchBlockChildren(n1.dynamicChildren, dynamicChildren, container, parentComponent, parentSuspense, isSVG);570 if ( parentComponent && parentComponent.type.__hmrId) {571 traverseStaticChildren(n1, n2);572 }573 else if (574 // #2080 if the stable fragment has a key, it's a <template v-for> that may575 // get moved around. Make sure all root level vnodes inherit el.576 // #2134 or if it's a component root, it may also get moved around577 // as the component is being moved.578 n2.key != null ||579 (parentComponent && n2 === parentComponent.subTree)) {580 traverseStaticChildren(n1, n2, true /* shallow */);581 }582 }583 else {584 // keyed / unkeyed, or manual fragments.585 // for keyed & unkeyed, since they are compiler generated from v-for,586 // each child is guaranteed to be a block so the fragment will never587 // have dynamicChildren.588 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);589 }590 }591 };592 const processElement = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {593 isSVG = isSVG || n2.type === 'svg';594 if (n1 == null) {595 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);596 }597 else {598 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);599 }600 };601 const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {602 let el;603 let vnodeHook;604 const { type, props, shapeFlag, transition, scopeId, patchFlag, dirs } = vnode;605 {606 el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is);607 // mount children first, since some props may rely on child content608 // being already rendered, e.g. `<select value>`609 if (shapeFlag & 8 /* TEXT_CHILDREN */) {610 hostSetElementText(el, vnode.children);611 }612 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {613 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', optimized || !!vnode.dynamicChildren);614 }615 if (dirs) {616 invokeDirectiveHook(vnode, null, parentComponent, 'created');617 }618 // props619 if (props) {620 for (const key in props) {621 if (!isReservedProp(key)) {622 hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);623 }624 }625 if ((vnodeHook = props.onVnodeBeforeMount)) {626 invokeVNodeHook(vnodeHook, parentComponent, vnode);627 }628 }629 // scopeId630 setScopeId(el, scopeId, vnode, parentComponent);631 }632 {633 Object.defineProperty(el, '__vnode', {634 value: vnode,635 enumerable: false636 });637 Object.defineProperty(el, '__vueParentComponent', {638 value: parentComponent,639 enumerable: false640 });641 }642 if (dirs) {643 invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount');644 }645 // #1583 For inside suspense + suspense not resolved case, enter hook should call when suspense resolved646 // #1689 For inside suspense + suspense resolved case, just call it647 const needCallTransitionHooks = (!parentSuspense || (parentSuspense && !parentSuspense.pendingBranch)) &&648 transition &&649 !transition.persisted;650 if (needCallTransitionHooks) {651 transition.beforeEnter(el);652 }653 hostInsert(el, container, anchor);654 if ((vnodeHook = props && props.onVnodeMounted) ||655 needCallTransitionHooks ||656 dirs) {657 queuePostRenderEffect(() => {658 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);659 needCallTransitionHooks && transition.enter(el);660 dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted');661 }, parentSuspense);662 }663 };664 const patchElement = (n1, n2, parentComponent, parentSuspense, isSVG, optimized) => {665 const el = (n2.el = n1.el);666 let { patchFlag, dynamicChildren, dirs } = n2;667 // #1426 take the old vnode's patch flag into account since user may clone a668 // compiler-generated vnode, which de-opts to FULL_PROPS669 patchFlag |= n1.patchFlag & 16 /* FULL_PROPS */;670 const oldProps = n1.props || EMPTY_OBJ;671 const newProps = n2.props || EMPTY_OBJ;672 let vnodeHook;673 if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {674 invokeVNodeHook(vnodeHook, parentComponent, n2, n1);675 }676 if (dirs) {677 invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate');678 }679 if ( isHmrUpdating) {680 // HMR updated, force full diff681 patchFlag = 0;682 optimized = false;683 dynamicChildren = null;684 }685 if (patchFlag > 0) {686 // the presence of a patchFlag means this element's render code was687 // generated by the compiler and can take the fast path.688 // in this path old node and new node are guaranteed to have the same shape689 // (i.e. at the exact same position in the source template)690 if (patchFlag & 16 /* FULL_PROPS */) {691 // element props contain dynamic keys, full diff needed692 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);693 }694 else {695 // class696 // this flag is matched when the element has dynamic class bindings.697 if (patchFlag & 2 /* CLASS */) {698 if (oldProps.class !== newProps.class) {699 hostPatchProp(el, 'class', null, newProps.class, isSVG);700 }701 }702 // style703 // this flag is matched when the element has dynamic style bindings704 if (patchFlag & 4 /* STYLE */) {705 hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG);706 }707 // props708 // This flag is matched when the element has dynamic prop/attr bindings709 // other than class and style. The keys of dynamic prop/attrs are saved for710 // faster iteration.711 // Note dynamic keys like :[foo]="bar" will cause this optimization to712 // bail out and go through a full diff because we need to unset the old key713 if (patchFlag & 8 /* PROPS */) {714 // if the flag is present then dynamicProps must be non-null715 const propsToUpdate = n2.dynamicProps;716 for (let i = 0; i < propsToUpdate.length; i++) {717 const key = propsToUpdate[i];718 const prev = oldProps[key];719 const next = newProps[key];720 if (next !== prev ||721 (hostForcePatchProp && hostForcePatchProp(el, key))) {722 hostPatchProp(el, key, prev, next, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);723 }724 }725 }726 }727 // text728 // This flag is matched when the element has only dynamic text children.729 if (patchFlag & 1 /* TEXT */) {730 if (n1.children !== n2.children) {731 hostSetElementText(el, n2.children);732 }733 }734 }735 else if (!optimized && dynamicChildren == null) {736 // unoptimized, full diff737 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);738 }739 const areChildrenSVG = isSVG && n2.type !== 'foreignObject';740 if (dynamicChildren) {741 patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, areChildrenSVG);742 if ( parentComponent && parentComponent.type.__hmrId) {743 traverseStaticChildren(n1, n2);744 }745 }746 else if (!optimized) {747 // full diff748 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, areChildrenSVG);749 }750 if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {751 queuePostRenderEffect(() => {752 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1);753 dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated');754 }, parentSuspense);755 }756 };757 const processComponent = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {758 if (n1 == null) {759 if (n2.shapeFlag & 512 /* COMPONENT_KEPT_ALIVE */) {760 parentComponent.ctx.activate(n2, container, anchor, isSVG, optimized);761 }762 else {763 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);764 }765 }766 else {767 updateComponent(n1, n2, optimized);768 }769 };770 const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {771 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent, parentSuspense));772 if ( instance.type.__hmrId) {773 registerHMR(instance);774 }775 {776 pushWarningContext(initialVNode);777 startMeasure(instance, `mount`);778 }779 // inject renderer internals for keepAlive780 if (isKeepAlive(initialVNode)) {781 instance.ctx.renderer = internals;782 }783 // resolve props and slots for setup context784 {785 startMeasure(instance, `init`);786 }787 setupComponent(instance);788 {789 endMeasure(instance, `init`);790 }791 // setup() is async. This component relies on async logic to be resolved792 // before proceeding793 if ( instance.asyncDep) {794 parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect);795 // Give it a placeholder if this is not hydration796 // TODO handle self-defined fallback797 if (!initialVNode.el) {798 const placeholder = (instance.subTree = createVNode(Comment));799 processCommentNode(null, placeholder, container, anchor);800 }801 return;802 }803 // setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized);804 setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized);805 {806 popWarningContext();807 endMeasure(instance, `mount`);808 }809 };810 function setupComponent(instance, isSSR = false) {811 isInSSRComponentSetup = isSSR;812 const { props, children, shapeFlag } = instance.vnode;813 const isStateful = shapeFlag & 4 /* STATEFUL_COMPONENT */;814 initProps(instance, props, isStateful, isSSR);815 initSlots(instance, children);816 const setupResult = isStateful817 ? setupStatefulComponent(instance, isSSR)818 : undefined;819 isInSSRComponentSetup = false;820 return setupResult;821 }822 function setupStatefulComponent(instance, isSSR) {823 const Component = instance.type;824 {825 if (Component.name) {826 validateComponentName(Component.name, instance.appContext.config);827 }828 if (Component.components) {829 const names = Object.keys(Component.components);830 for (let i = 0; i < names.length; i++) {831 validateComponentName(names[i], instance.appContext.config);832 }833 }834 if (Component.directives) {835 const names = Object.keys(Component.directives);836 for (let i = 0; i < names.length; i++) {837 validateDirectiveName(names[i]);838 }839 }840 }841 // 0. create render proxy property access cache842 instance.accessCache = {};843 // 1. create public instance / render proxy844 // also mark it raw so it's never observed845 instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers);846 {847 exposePropsOnRenderContext(instance);848 }849 // 2. call setup()850 const { setup } = Component;851 if (setup) {...
note.js
Source:note.js
...66 return app;67 },68 directive(name, directive) {69 {70 validateDirectiveName(name);71 }72 if (!directive) {73 return context.directives[name];74 }75 if ( context.directives[name]) {76 warn(`Directive "${name}" has already been registered in target app.`);77 }78 context.directives[name] = directive;79 return app;80 },81 mount(rootContainer, isHydrate) {82 if (!isMounted) {83 const vnode = createVNode(rootComponent, rootProps);84 // store app context on the root VNode.85 // this will be set on the root instance on initial mount.86 vnode.appContext = context;87 // HMR root reload88 {89 context.reload = () => {90 render(cloneVNode(vnode), rootContainer);91 };92 }93 if (isHydrate && hydrate) {94 hydrate(vnode, rootContainer);95 }96 else {97 render(vnode, rootContainer);98 }99 isMounted = true;100 app._container = rootContainer;101 rootContainer.__vue_app__ = app;102 {103 devtoolsInitApp(app, version);104 }105 return vnode.component.proxy;106 }107 else {108 warn(`App has already been mounted.\n` +109 `If you want to remount the same app, move your app creation logic ` +110 `into a factory function and create fresh app instances for each ` +111 `mount - e.g. \`const createMyApp = () => createApp(App)\``);112 }113 },114 unmount() {115 if (isMounted) {116 render(null, app._container);117 {118 devtoolsUnmountApp(app);119 }120 }121 else {122 warn(`Cannot unmount an app that is not mounted.`);123 }124 },125 provide(key, value) {126 if ( key in context.provides) {127 warn(`App already provides property with key "${String(key)}". ` +128 `It will be overwritten with the new value.`);129 }130 // TypeScript doesn't allow symbols as index type131 // https://github.com/Microsoft/TypeScript/issues/24587132 context.provides[key] = value;133 return app;134 }135 });136 return app;137};138// app context139function createAppContext() {140 return {141 app: null,142 config: {143 isNativeTag: NO,144 performance: false,145 globalProperties: {},146 optionMergeStrategies: {},147 isCustomElement: NO,148 errorHandler: undefined,149 warnHandler: undefined150 },151 mixins: [],152 components: {},153 directives: {},154 provides: Object.create(null)155 };156}157/**158 * mount159 * 1. createVNode(rootComponent, rootProps)160 * 2. render(cloneVNode(vnode), rootContainer) | hydrate(vnode, rootContainer);161 * 3. devtoolsInitApp(app, version);162 */163function mount(rootContainer, isHydrate) {164 if (!isMounted) {165 const vnode = createVNode(rootComponent, rootProps);166 // store app context on the root VNode.167 // this will be set on the root instance on initial mount.168 vnode.appContext = context;169 // HMR root reload170 {171 context.reload = () => {172 render(cloneVNode(vnode), rootContainer);173 };174 }175 if (isHydrate && hydrate) {176 hydrate(vnode, rootContainer);177 }178 else {179 render(vnode, rootContainer);180 }181 isMounted = true;182 app._container = rootContainer;183 rootContainer.__vue_app__ = app;184 {185 devtoolsInitApp(app, version);186 }187 return vnode.component.proxy;188 }189 else {190 warn(`App has already been mounted.\n` +191 `If you want to remount the same app, move your app creation logic ` +192 `into a factory function and create fresh app instances for each ` +193 `mount - e.g. \`const createMyApp = () => createApp(App)\``);194 }195}196// createVNode 2997197const createVNode = ( createVNodeWithArgsTransform);198const createVNodeWithArgsTransform = (...args) => {199 return _createVNode(...(vnodeArgsTransformer ? vnodeArgsTransformer(args, currentRenderingInstance) : args))200}201function _createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, isBlockNode = false) {202 if (!type || type === NULL_DYNAMIC_COMPONENT) {203 if ( !type) {204 warn(`Invalid vnode type when creating vnode: ${type}.`);205 }206 type = Comment;207 }208 if (isVNode(type)) {209 // createVNode receiving an existing vnode. This happens in cases like210 // <component :is="vnode"/>211 // #2078 make sure to merge refs during the clone instead of overwriting it212 const cloned = cloneVNode(type, props, true /* mergeRef: true */);213 if (children) {214 normalizeChildren(cloned, children);215 }216 return cloned;217 }218 // class component normalization.219 if (isClassComponent(type)) {220 type = type.__vccOpts;221 }222 // class & style normalization.223 if (props) {224 // for reactive or proxy objects, we need to clone it to enable mutation.225 if (isProxy(props) || InternalObjectKey in props) {226 props = extend({}, props);227 }228 let { class: klass, style } = props;229 if (klass && !isString(klass)) {230 props.class = normalizeClass(klass);231 }232 if (isObject(style)) {233 // reactive state objects need to be cloned since they are likely to be234 // mutated235 if (isProxy(style) && !isArray(style)) {236 style = extend({}, style);237 }238 props.style = normalizeStyle(style);239 }240 }241 // encode the vnode type information into a bitmap242 const shapeFlag = isString(type)243 ? 1 /* ELEMENT */244 : isSuspense(type)245 ? 128 /* SUSPENSE */246 : isTeleport(type)247 ? 64 /* TELEPORT */248 : isObject(type)249 ? 4 /* STATEFUL_COMPONENT */250 : isFunction(type)251 ? 2 /* FUNCTIONAL_COMPONENT */252 : 0;253 if ( shapeFlag & 4 /* STATEFUL_COMPONENT */ && isProxy(type)) {254 type = toRaw(type);255 warn(`Vue received a Component which was made a reactive object. This can ` +256 `lead to unnecessary performance overhead, and should be avoided by ` +257 `marking the component with \`markRaw\` or using \`shallowRef\` ` +258 `instead of \`ref\`.`, `\nComponent that was made reactive: `, type);259 }260 const vnode = {261 __v_isVNode: true,262 ["__v_skip" /* SKIP */]: true,263 type,264 props,265 key: props && normalizeKey(props),266 ref: props && normalizeRef(props),267 scopeId: currentScopeId,268 children: null,269 component: null,270 suspense: null,271 ssContent: null,272 ssFallback: null,273 dirs: null,274 transition: null,275 el: null,276 anchor: null,277 target: null,278 targetAnchor: null,279 staticCount: 0,280 shapeFlag,281 patchFlag,282 dynamicProps,283 dynamicChildren: null,284 appContext: null285 };286 // validate key287 if ( vnode.key !== vnode.key) {288 warn(`VNode created with invalid key (NaN). VNode type:`, vnode.type);289 }290 normalizeChildren(vnode, children);291 // normalize suspense children292 if ( shapeFlag & 128 /* SUSPENSE */) {293 const { content, fallback } = normalizeSuspenseChildren(vnode);294 vnode.ssContent = content;295 vnode.ssFallback = fallback;296 }297 if (shouldTrack$1 > 0 &&298 // avoid a block node from tracking itself299 !isBlockNode &&300 // has current parent block301 currentBlock &&302 // presence of a patch flag indicates this node needs patching on updates.303 // component nodes also should always be patched, because even if the304 // component doesn't need to update, it needs to persist the instance on to305 // the next vnode so that it can be properly unmounted later.306 (patchFlag > 0 || shapeFlag & 6 /* COMPONENT */) &&307 // the EVENTS flag is only for hydration and if it is the only flag, the308 // vnode should not be considered dynamic due to handler caching.309 patchFlag !== 32 /* HYDRATE_EVENTS */) {310 currentBlock.push(vnode);311 }312 return vnode;313}314// render 8936315const render = ((...args) => {316 ensureRenderer().render(...args);317});318function ensureRenderer() { // 8925319 return renderer || (renderer = createRenderer(rendererOptions));320}321function createRenderer(options) {322 return baseCreateRenderer(options);323}324// implementation 5106325function baseCreateRenderer(options, createHydrationFns) {326 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, forcePatchProp: hostForcePatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, setScopeId: hostSetScopeId = NOOP, cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent } = options;327 // Note: functions inside this closure should use `const xxx = () => {}`328 // style in order to prevent being inlined by minifiers.329 const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) => {330 // patching & not same type, unmount old tree331 if (n1 && !isSameVNodeType(n1, n2)) {332 anchor = getNextHostNode(n1);333 unmount(n1, parentComponent, parentSuspense, true);334 n1 = null;335 }336 if (n2.patchFlag === -2 /* BAIL */) {337 optimized = false;338 n2.dynamicChildren = null;339 }340 const { type, ref, shapeFlag } = n2;341 switch (type) {342 case Text:343 processText(n1, n2, container, anchor);344 break;345 case Comment:346 processCommentNode(n1, n2, container, anchor);347 break;348 case Static:349 if (n1 == null) {350 mountStaticNode(n2, container, anchor, isSVG);351 }352 else {353 patchStaticNode(n1, n2, container, isSVG);354 }355 break;356 case Fragment:357 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);358 break;359 default:360 if (shapeFlag & 1 /* ELEMENT */) {361 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);362 }363 else if (shapeFlag & 6 /* COMPONENT */) {364 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);365 }366 else if (shapeFlag & 64 /* TELEPORT */) {367 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);368 }369 else if ( shapeFlag & 128 /* SUSPENSE */) {370 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);371 }372 else {373 warn('Invalid VNode type:', type, `(${typeof type})`);374 }375 }376 // set ref377 if (ref != null && parentComponent) {378 setRef(ref, n1 && n1.ref, parentComponent, parentSuspense, n2);379 }380 };381 const processText = (n1, n2, container, anchor) => {382 if (n1 == null) {383 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);384 }385 else {386 const el = (n2.el = n1.el);387 if (n2.children !== n1.children) {388 hostSetText(el, n2.children);389 }390 }391 };392 const processCommentNode = (n1, n2, container, anchor) => {393 if (n1 == null) {394 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);395 }396 else {397 // there's no support for dynamic comments398 n2.el = n1.el;399 }400 };401 const mountStaticNode = (n2, container, anchor, isSVG) => {402 [n2.el, n2.anchor] = hostInsertStaticContent(n2.children, container, anchor, isSVG);403 };404 /**405 * Dev / HMR only406 */407 const patchStaticNode = (n1, n2, container, isSVG) => {408 // static nodes are only patched during dev for HMR409 if (n2.children !== n1.children) {410 const anchor = hostNextSibling(n1.anchor);411 // remove existing412 removeStaticNode(n1);413 [n2.el, n2.anchor] = hostInsertStaticContent(n2.children, container, anchor, isSVG);414 }415 else {416 n2.el = n1.el;417 n2.anchor = n1.anchor;418 }419 };420 /**421 * Dev / HMR only422 */423 const moveStaticNode = (vnode, container, anchor) => {424 let cur = vnode.el;425 const end = vnode.anchor;426 while (cur && cur !== end) {427 const next = hostNextSibling(cur);428 hostInsert(cur, container, anchor);429 cur = next;430 }431 hostInsert(end, container, anchor);432 };433 /**434 * Dev / HMR only435 */436 const removeStaticNode = (vnode) => {437 let cur = vnode.el;438 while (cur && cur !== vnode.anchor) {439 const next = hostNextSibling(cur);440 hostRemove(cur);441 cur = next;442 }443 hostRemove(vnode.anchor);444 };445 const processElement = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {446 isSVG = isSVG || n2.type === 'svg';447 if (n1 == null) {448 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);449 }450 else {451 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);452 }453 };454 const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {455 let el;456 let vnodeHook;457 const { type, props, shapeFlag, transition, scopeId, patchFlag, dirs } = vnode;458 {459 el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is);460 // mount children first, since some props may rely on child content461 // being already rendered, e.g. `<select value>`462 if (shapeFlag & 8 /* TEXT_CHILDREN */) {463 hostSetElementText(el, vnode.children);464 }465 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {466 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', optimized || !!vnode.dynamicChildren);467 }468 if (dirs) {469 invokeDirectiveHook(vnode, null, parentComponent, 'created');470 }471 // props472 if (props) {473 for (const key in props) {474 if (!isReservedProp(key)) {475 hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);476 }477 }478 if ((vnodeHook = props.onVnodeBeforeMount)) {479 invokeVNodeHook(vnodeHook, parentComponent, vnode);480 }481 }482 // scopeId483 setScopeId(el, scopeId, vnode, parentComponent);484 }485 {486 Object.defineProperty(el, '__vnode', {487 value: vnode,488 enumerable: false489 });490 Object.defineProperty(el, '__vueParentComponent', {491 value: parentComponent,492 enumerable: false493 });494 }495 if (dirs) {496 invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount');497 }498 // #1583 For inside suspense + suspense not resolved case, enter hook should call when suspense resolved499 // #1689 For inside suspense + suspense resolved case, just call it500 const needCallTransitionHooks = (!parentSuspense || (parentSuspense && !parentSuspense.pendingBranch)) &&501 transition &&502 !transition.persisted;503 if (needCallTransitionHooks) {504 transition.beforeEnter(el);505 }506 hostInsert(el, container, anchor);507 if ((vnodeHook = props && props.onVnodeMounted) ||508 needCallTransitionHooks ||509 dirs) {510 queuePostRenderEffect(() => {511 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);512 needCallTransitionHooks && transition.enter(el);513 dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted');514 }, parentSuspense);515 }516 };517 const setScopeId = (el, scopeId, vnode, parentComponent) => {518 if (scopeId) {519 hostSetScopeId(el, scopeId);520 }521 if (parentComponent) {522 const treeOwnerId = parentComponent.type.__scopeId;523 // vnode's own scopeId and the current patched component's scopeId is524 // different - this is a slot content node.525 if (treeOwnerId && treeOwnerId !== scopeId) {526 hostSetScopeId(el, treeOwnerId + '-s');527 }528 let subTree = parentComponent.subTree;529 if ( subTree.type === Fragment) {530 subTree =531 filterSingleRoot(subTree.children) || subTree;532 }533 if (vnode === subTree) {534 setScopeId(el, parentComponent.vnode.scopeId, parentComponent.vnode, parentComponent.parent);535 }536 }537 };538 const mountChildren = (children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) => {539 for (let i = start; i < children.length; i++) {540 const child = (children[i] = optimized541 ? cloneIfMounted(children[i])542 : normalizeVNode(children[i]));543 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);544 }545 };546 const patchElement = (n1, n2, parentComponent, parentSuspense, isSVG, optimized) => {547 const el = (n2.el = n1.el);548 let { patchFlag, dynamicChildren, dirs } = n2;549 // #1426 take the old vnode's patch flag into account since user may clone a550 // compiler-generated vnode, which de-opts to FULL_PROPS551 patchFlag |= n1.patchFlag & 16 /* FULL_PROPS */;552 const oldProps = n1.props || EMPTY_OBJ;553 const newProps = n2.props || EMPTY_OBJ;554 let vnodeHook;555 if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {556 invokeVNodeHook(vnodeHook, parentComponent, n2, n1);557 }558 if (dirs) {559 invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate');560 }561 if ( isHmrUpdating) {562 // HMR updated, force full diff563 patchFlag = 0;564 optimized = false;565 dynamicChildren = null;566 }567 if (patchFlag > 0) {568 // the presence of a patchFlag means this element's render code was569 // generated by the compiler and can take the fast path.570 // in this path old node and new node are guaranteed to have the same shape571 // (i.e. at the exact same position in the source template)572 if (patchFlag & 16 /* FULL_PROPS */) {573 // element props contain dynamic keys, full diff needed574 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);575 }576 else {577 // class578 // this flag is matched when the element has dynamic class bindings.579 if (patchFlag & 2 /* CLASS */) {580 if (oldProps.class !== newProps.class) {581 hostPatchProp(el, 'class', null, newProps.class, isSVG);582 }583 }584 // style585 // this flag is matched when the element has dynamic style bindings586 if (patchFlag & 4 /* STYLE */) {587 hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG);588 }589 // props590 // This flag is matched when the element has dynamic prop/attr bindings591 // other than class and style. The keys of dynamic prop/attrs are saved for592 // faster iteration.593 // Note dynamic keys like :[foo]="bar" will cause this optimization to594 // bail out and go through a full diff because we need to unset the old key595 if (patchFlag & 8 /* PROPS */) {596 // if the flag is present then dynamicProps must be non-null597 const propsToUpdate = n2.dynamicProps;598 for (let i = 0; i < propsToUpdate.length; i++) {599 const key = propsToUpdate[i];600 const prev = oldProps[key];601 const next = newProps[key];602 if (next !== prev ||603 (hostForcePatchProp && hostForcePatchProp(el, key))) {604 hostPatchProp(el, key, prev, next, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);605 }606 }607 }608 }609 // text610 // This flag is matched when the element has only dynamic text children.611 if (patchFlag & 1 /* TEXT */) {612 if (n1.children !== n2.children) {613 hostSetElementText(el, n2.children);614 }615 }616 }617 else if (!optimized && dynamicChildren == null) {618 // unoptimized, full diff619 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);620 }621 const areChildrenSVG = isSVG && n2.type !== 'foreignObject';622 if (dynamicChildren) {623 patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, areChildrenSVG);624 if ( parentComponent && parentComponent.type.__hmrId) {625 traverseStaticChildren(n1, n2);626 }627 }628 else if (!optimized) {629 // full diff630 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, areChildrenSVG);631 }632 if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {633 queuePostRenderEffect(() => {634 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1);635 dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated');636 }, parentSuspense);637 }638 };639 // The fast path for blocks.640 const patchBlockChildren = (oldChildren, newChildren, fallbackContainer, parentComponent, parentSuspense, isSVG) => {641 for (let i = 0; i < newChildren.length; i++) {642 const oldVNode = oldChildren[i];643 const newVNode = newChildren[i];644 // Determine the container (parent element) for the patch.645 const container = 646 // - In the case of a Fragment, we need to provide the actual parent647 // of the Fragment itself so it can move its children.648 oldVNode.type === Fragment ||649 // - In the case of different nodes, there is going to be a replacement650 // which also requires the correct parent container651 !isSameVNodeType(oldVNode, newVNode) ||652 // - In the case of a component, it could contain anything.653 oldVNode.shapeFlag & 6 /* COMPONENT */ ||654 oldVNode.shapeFlag & 64 /* TELEPORT */655 ? hostParentNode(oldVNode.el)656 : // In other cases, the parent container is not actually used so we657 // just pass the block element here to avoid a DOM parentNode call.658 fallbackContainer;659 patch(oldVNode, newVNode, container, null, parentComponent, parentSuspense, isSVG, true);660 }661 };662 const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {663 if (oldProps !== newProps) {664 for (const key in newProps) {665 if (isReservedProp(key))666 continue;667 const next = newProps[key];668 const prev = oldProps[key];669 if (next !== prev ||670 (hostForcePatchProp && hostForcePatchProp(el, key))) {671 hostPatchProp(el, key, prev, next, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);672 }673 }674 if (oldProps !== EMPTY_OBJ) {675 for (const key in oldProps) {676 if (!isReservedProp(key) && !(key in newProps)) {677 hostPatchProp(el, key, oldProps[key], null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);678 }679 }680 }681 }682 };683 const processFragment = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {684 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''));685 const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''));686 let { patchFlag, dynamicChildren } = n2;687 if (patchFlag > 0) {688 optimized = true;689 }690 if ( isHmrUpdating) {691 // HMR updated, force full diff692 patchFlag = 0;693 optimized = false;694 dynamicChildren = null;695 }696 if (n1 == null) {697 hostInsert(fragmentStartAnchor, container, anchor);698 hostInsert(fragmentEndAnchor, container, anchor);699 // a fragment can only have array children700 // since they are either generated by the compiler, or implicitly created701 // from arrays.702 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);703 }704 else {705 if (patchFlag > 0 &&706 patchFlag & 64 /* STABLE_FRAGMENT */ &&707 dynamicChildren) {708 // a stable fragment (template root or <template v-for>) doesn't need to709 // patch children order, but it may contain dynamicChildren.710 patchBlockChildren(n1.dynamicChildren, dynamicChildren, container, parentComponent, parentSuspense, isSVG);711 if ( parentComponent && parentComponent.type.__hmrId) {712 traverseStaticChildren(n1, n2);713 }714 else if (715 // #2080 if the stable fragment has a key, it's a <template v-for> that may716 // get moved around. Make sure all root level vnodes inherit el.717 // #2134 or if it's a component root, it may also get moved around718 // as the component is being moved.719 n2.key != null ||720 (parentComponent && n2 === parentComponent.subTree)) {721 traverseStaticChildren(n1, n2, true /* shallow */);722 }723 }724 else {725 // keyed / unkeyed, or manual fragments.726 // for keyed & unkeyed, since they are compiler generated from v-for,727 // each child is guaranteed to be a block so the fragment will never728 // have dynamicChildren.729 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);730 }731 }732 };733 const processComponent = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {734 if (n1 == null) {735 if (n2.shapeFlag & 512 /* COMPONENT_KEPT_ALIVE */) {736 parentComponent.ctx.activate(n2, container, anchor, isSVG, optimized);737 }738 else {739 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);740 }741 }742 else {743 updateComponent(n1, n2, optimized);744 }745 };746 const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {747 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent, parentSuspense));748 if ( instance.type.__hmrId) {749 registerHMR(instance);750 }751 {752 pushWarningContext(initialVNode);753 startMeasure(instance, `mount`);754 }755 // inject renderer internals for keepAlive756 if (isKeepAlive(initialVNode)) {757 instance.ctx.renderer = internals;758 }759 // resolve props and slots for setup context760 {761 startMeasure(instance, `init`);762 }763 setupComponent(instance);764 {765 endMeasure(instance, `init`);766 }767 // setup() is async. This component relies on async logic to be resolved768 // before proceeding769 if ( instance.asyncDep) {770 parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect);771 // Give it a placeholder if this is not hydration772 // TODO handle self-defined fallback773 if (!initialVNode.el) {774 const placeholder = (instance.subTree = createVNode(Comment));775 processCommentNode(null, placeholder, container, anchor);776 }777 return;778 }779 setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized);780 {781 popWarningContext();782 endMeasure(instance, `mount`);783 }784 };785 const updateComponent = (n1, n2, optimized) => {786 const instance = (n2.component = n1.component);787 if (shouldUpdateComponent(n1, n2, optimized)) {788 if (789 instance.asyncDep &&790 !instance.asyncResolved) {791 // async & still pending - just update props and slots792 // since the component's reactive effect for render isn't set-up yet793 {794 pushWarningContext(n2);795 }796 updateComponentPreRender(instance, n2, optimized);797 {798 popWarningContext();799 }800 return;801 }802 else {803 // normal update804 instance.next = n2;805 // in case the child component is also queued, remove it to avoid806 // double updating the same child component in the same flush.807 invalidateJob(instance.update);808 // instance.update is the reactive effect runner.809 instance.update();810 }811 }812 else {813 // no update needed. just copy over properties814 n2.component = n1.component;815 n2.el = n1.el;816 instance.vnode = n2;817 }818 };819 const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {820 // create reactive effect for rendering821 instance.update = effect(function componentEffect() {822 if (!instance.isMounted) {823 let vnodeHook;824 const { el, props } = initialVNode;825 const { bm, m, parent } = instance;826 // beforeMount hook827 if (bm) {828 invokeArrayFns(bm);829 }830 // onVnodeBeforeMount831 if ((vnodeHook = props && props.onVnodeBeforeMount)) {832 invokeVNodeHook(vnodeHook, parent, initialVNode);833 }834 // render835 {836 startMeasure(instance, `render`);837 }838 const subTree = (instance.subTree = renderComponentRoot(instance));839 {840 endMeasure(instance, `render`);841 }842 if (el && hydrateNode) {843 {844 startMeasure(instance, `hydrate`);845 }846 // vnode has adopted host node - perform hydration instead of mount.847 hydrateNode(initialVNode.el, subTree, instance, parentSuspense);848 {849 endMeasure(instance, `hydrate`);850 }851 }852 else {853 {854 startMeasure(instance, `patch`);855 }856 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);857 {858 endMeasure(instance, `patch`);859 }860 initialVNode.el = subTree.el;861 }862 // mounted hook863 if (m) {864 queuePostRenderEffect(m, parentSuspense);865 }866 // onVnodeMounted867 if ((vnodeHook = props && props.onVnodeMounted)) {868 queuePostRenderEffect(() => {869 invokeVNodeHook(vnodeHook, parent, initialVNode);870 }, parentSuspense);871 }872 // activated hook for keep-alive roots.873 // #1742 activated hook must be accessed after first render874 // since the hook may be injected by a child keep-alive875 const { a } = instance;876 if (a &&877 initialVNode.shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {878 queuePostRenderEffect(a, parentSuspense);879 }880 instance.isMounted = true;881 }882 else {883 // updateComponent884 // This is triggered by mutation of component's own state (next: null)885 // OR parent calling processComponent (next: VNode)886 let { next, bu, u, parent, vnode } = instance;887 let originNext = next;888 let vnodeHook;889 {890 pushWarningContext(next || instance.vnode);891 }892 if (next) {893 updateComponentPreRender(instance, next, optimized);894 }895 else {896 next = vnode;897 }898 next.el = vnode.el;899 // beforeUpdate hook900 if (bu) {901 invokeArrayFns(bu);902 }903 // onVnodeBeforeUpdate904 if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {905 invokeVNodeHook(vnodeHook, parent, next, vnode);906 }907 // render908 {909 startMeasure(instance, `render`);910 }911 const nextTree = renderComponentRoot(instance);912 {913 endMeasure(instance, `render`);914 }915 const prevTree = instance.subTree;916 instance.subTree = nextTree;917 // reset refs918 // only needed if previous patch had refs919 if (instance.refs !== EMPTY_OBJ) {920 instance.refs = {};921 }922 {923 startMeasure(instance, `patch`);924 }925 patch(prevTree, nextTree, 926 // parent may have changed if it's in a teleport927 hostParentNode(prevTree.el), 928 // anchor may have changed if it's in a fragment929 getNextHostNode(prevTree), instance, parentSuspense, isSVG);930 {931 endMeasure(instance, `patch`);932 }933 next.el = nextTree.el;934 if (originNext === null) {935 // self-triggered update. In case of HOC, update parent component936 // vnode el. HOC is indicated by parent instance's subTree pointing937 // to child component's vnode938 updateHOCHostEl(instance, nextTree.el);939 }940 // updated hook941 if (u) {942 queuePostRenderEffect(u, parentSuspense);943 }944 // onVnodeUpdated945 if ((vnodeHook = next.props && next.props.onVnodeUpdated)) {946 queuePostRenderEffect(() => {947 invokeVNodeHook(vnodeHook, parent, next, vnode);948 }, parentSuspense);949 }950 {951 devtoolsComponentUpdated(instance);952 }953 {954 popWarningContext();955 }956 }957 }, createDevEffectOptions(instance) );958 };959 const updateComponentPreRender = (instance, nextVNode, optimized) => {960 nextVNode.component = instance;961 const prevProps = instance.vnode.props;962 instance.vnode = nextVNode;963 instance.next = null;964 updateProps(instance, nextVNode.props, prevProps, optimized);965 updateSlots(instance, nextVNode.children);966 // props update may have triggered pre-flush watchers.967 // flush them before the render update.968 flushPreFlushCbs(undefined, instance.update);969 };970 const patchChildren = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized = false) => {971 const c1 = n1 && n1.children;972 const prevShapeFlag = n1 ? n1.shapeFlag : 0;973 const c2 = n2.children;974 const { patchFlag, shapeFlag } = n2;975 // fast path976 if (patchFlag > 0) {977 if (patchFlag & 128 /* KEYED_FRAGMENT */) {978 // this could be either fully-keyed or mixed (some keyed some not)979 // presence of patchFlag means children are guaranteed to be arrays980 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);981 return;982 }983 else if (patchFlag & 256 /* UNKEYED_FRAGMENT */) {984 // unkeyed985 patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);986 return;987 }988 }989 // children has 3 possibilities: text, array or no children.990 if (shapeFlag & 8 /* TEXT_CHILDREN */) {991 // text children fast path992 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {993 unmountChildren(c1, parentComponent, parentSuspense);994 }995 if (c2 !== c1) {996 hostSetElementText(container, c2);997 }998 }999 else {1000 if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {1001 // prev children was array1002 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1003 // two arrays, cannot assume anything, do full diff1004 patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1005 }1006 else {1007 // no new children, just unmount old1008 unmountChildren(c1, parentComponent, parentSuspense, true);1009 }1010 }1011 else {1012 // prev children was text OR null1013 // new children is array OR null1014 if (prevShapeFlag & 8 /* TEXT_CHILDREN */) {1015 hostSetElementText(container, '');1016 }1017 // mount new if array1018 if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1019 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1020 }1021 }1022 }1023 };1024 const patchUnkeyedChildren = (c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {1025 c1 = c1 || EMPTY_ARR;1026 c2 = c2 || EMPTY_ARR;1027 const oldLength = c1.length;1028 const newLength = c2.length;1029 const commonLength = Math.min(oldLength, newLength);1030 let i;1031 for (i = 0; i < commonLength; i++) {1032 const nextChild = (c2[i] = optimized1033 ? cloneIfMounted(c2[i])1034 : normalizeVNode(c2[i]));1035 patch(c1[i], nextChild, container, null, parentComponent, parentSuspense, isSVG, optimized);1036 }1037 if (oldLength > newLength) {1038 // remove old1039 unmountChildren(c1, parentComponent, parentSuspense, true, commonLength);1040 }1041 else {1042 // mount new1043 mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, commonLength);1044 }1045 };1046 // can be all-keyed or mixed1047 const patchKeyedChildren = (c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) => {1048 let i = 0;1049 const l2 = c2.length;1050 let e1 = c1.length - 1; // prev ending index1051 let e2 = l2 - 1; // next ending index1052 // 1. sync from start1053 // (a b) c1054 // (a b) d e1055 while (i <= e1 && i <= e2) {1056 const n1 = c1[i];1057 const n2 = (c2[i] = optimized1058 ? cloneIfMounted(c2[i])1059 : normalizeVNode(c2[i]));1060 if (isSameVNodeType(n1, n2)) {1061 patch(n1, n2, container, null, parentComponent, parentSuspense, isSVG, optimized);1062 }1063 else {1064 break;1065 }1066 i++;1067 }1068 // 2. sync from end1069 // a (b c)1070 // d e (b c)1071 while (i <= e1 && i <= e2) {1072 const n1 = c1[e1];1073 const n2 = (c2[e2] = optimized1074 ? cloneIfMounted(c2[e2])1075 : normalizeVNode(c2[e2]));1076 if (isSameVNodeType(n1, n2)) {1077 patch(n1, n2, container, null, parentComponent, parentSuspense, isSVG, optimized);1078 }1079 else {1080 break;1081 }1082 e1--;1083 e2--;1084 }1085 // 3. common sequence + mount1086 // (a b)1087 // (a b) c1088 // i = 2, e1 = 1, e2 = 21089 // (a b)1090 // c (a b)1091 // i = 0, e1 = -1, e2 = 01092 if (i > e1) {1093 if (i <= e2) {1094 const nextPos = e2 + 1;1095 const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;1096 while (i <= e2) {1097 patch(null, (c2[i] = optimized1098 ? cloneIfMounted(c2[i])1099 : normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);1100 i++;1101 }1102 }1103 }1104 // 4. common sequence + unmount1105 // (a b) c1106 // (a b)1107 // i = 2, e1 = 2, e2 = 11108 // a (b c)1109 // (b c)1110 // i = 0, e1 = 0, e2 = -11111 else if (i > e2) {1112 while (i <= e1) {1113 unmount(c1[i], parentComponent, parentSuspense, true);1114 i++;1115 }1116 }1117 // 5. unknown sequence1118 // [i ... e1 + 1]: a b [c d e] f g1119 // [i ... e2 + 1]: a b [e d c h] f g1120 // i = 2, e1 = 4, e2 = 51121 else {1122 const s1 = i; // prev starting index1123 const s2 = i; // next starting index1124 // 5.1 build key:index map for newChildren1125 const keyToNewIndexMap = new Map();1126 for (i = s2; i <= e2; i++) {1127 const nextChild = (c2[i] = optimized1128 ? cloneIfMounted(c2[i])1129 : normalizeVNode(c2[i]));1130 if (nextChild.key != null) {1131 if ( keyToNewIndexMap.has(nextChild.key)) {1132 warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);1133 }1134 keyToNewIndexMap.set(nextChild.key, i);1135 }1136 }1137 // 5.2 loop through old children left to be patched and try to patch1138 // matching nodes & remove nodes that are no longer present1139 let j;1140 let patched = 0;1141 const toBePatched = e2 - s2 + 1;1142 let moved = false;1143 // used to track whether any node has moved1144 let maxNewIndexSoFar = 0;1145 // works as Map<newIndex, oldIndex>1146 // Note that oldIndex is offset by +11147 // and oldIndex = 0 is a special value indicating the new node has1148 // no corresponding old node.1149 // used for determining longest stable subsequence1150 const newIndexToOldIndexMap = new Array(toBePatched);1151 for (i = 0; i < toBePatched; i++)1152 newIndexToOldIndexMap[i] = 0;1153 for (i = s1; i <= e1; i++) {1154 const prevChild = c1[i];1155 if (patched >= toBePatched) {1156 // all new children have been patched so this can only be a removal1157 unmount(prevChild, parentComponent, parentSuspense, true);1158 continue;1159 }1160 let newIndex;1161 if (prevChild.key != null) {1162 newIndex = keyToNewIndexMap.get(prevChild.key);1163 }1164 else {1165 // key-less node, try to locate a key-less node of the same type1166 for (j = s2; j <= e2; j++) {1167 if (newIndexToOldIndexMap[j - s2] === 0 &&1168 isSameVNodeType(prevChild, c2[j])) {1169 newIndex = j;1170 break;1171 }1172 }1173 }1174 if (newIndex === undefined) {1175 unmount(prevChild, parentComponent, parentSuspense, true);1176 }1177 else {1178 newIndexToOldIndexMap[newIndex - s2] = i + 1;1179 if (newIndex >= maxNewIndexSoFar) {1180 maxNewIndexSoFar = newIndex;1181 }1182 else {1183 moved = true;1184 }1185 patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);1186 patched++;1187 }1188 }1189 // 5.3 move and mount1190 // generate longest stable subsequence only when nodes have moved1191 const increasingNewIndexSequence = moved1192 ? getSequence(newIndexToOldIndexMap)1193 : EMPTY_ARR;1194 j = increasingNewIndexSequence.length - 1;1195 // looping backwards so that we can use last patched node as anchor1196 for (i = toBePatched - 1; i >= 0; i--) {1197 const nextIndex = s2 + i;1198 const nextChild = c2[nextIndex];1199 const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : parentAnchor;1200 if (newIndexToOldIndexMap[i] === 0) {1201 // mount new1202 patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);1203 }1204 else if (moved) {1205 // move if:1206 // There is no stable subsequence (e.g. a reverse)1207 // OR current node is not among the stable sequence1208 if (j < 0 || i !== increasingNewIndexSequence[j]) {1209 move(nextChild, container, anchor, 2 /* REORDER */);1210 }1211 else {1212 j--;1213 }1214 }1215 }1216 }1217 };1218 const move = (vnode, container, anchor, moveType, parentSuspense = null) => {1219 const { el, type, transition, children, shapeFlag } = vnode;1220 if (shapeFlag & 6 /* COMPONENT */) {1221 move(vnode.component.subTree, container, anchor, moveType);1222 return;1223 }1224 if ( shapeFlag & 128 /* SUSPENSE */) {1225 vnode.suspense.move(container, anchor, moveType);1226 return;1227 }1228 if (shapeFlag & 64 /* TELEPORT */) {1229 type.move(vnode, container, anchor, internals);1230 return;1231 }1232 if (type === Fragment) {1233 hostInsert(el, container, anchor);1234 for (let i = 0; i < children.length; i++) {1235 move(children[i], container, anchor, moveType);1236 }1237 hostInsert(vnode.anchor, container, anchor);1238 return;1239 }1240 // static node move can only happen when force updating HMR1241 if ( type === Static) {1242 moveStaticNode(vnode, container, anchor);1243 return;1244 }1245 // single nodes1246 const needTransition = moveType !== 2 /* REORDER */ &&1247 shapeFlag & 1 /* ELEMENT */ &&1248 transition;1249 if (needTransition) {1250 if (moveType === 0 /* ENTER */) {1251 transition.beforeEnter(el);1252 hostInsert(el, container, anchor);1253 queuePostRenderEffect(() => transition.enter(el), parentSuspense);1254 }1255 else {1256 const { leave, delayLeave, afterLeave } = transition;1257 const remove = () => hostInsert(el, container, anchor);1258 const performLeave = () => {1259 leave(el, () => {1260 remove();1261 afterLeave && afterLeave();1262 });1263 };1264 if (delayLeave) {1265 delayLeave(el, remove, performLeave);1266 }1267 else {1268 performLeave();1269 }1270 }1271 }1272 else {1273 hostInsert(el, container, anchor);1274 }1275 };1276 const unmount = (vnode, parentComponent, parentSuspense, doRemove = false) => {1277 const { type, props, ref, children, dynamicChildren, shapeFlag, patchFlag, dirs } = vnode;1278 // unset ref1279 if (ref != null && parentComponent) {1280 setRef(ref, null, parentComponent, parentSuspense, null);1281 }1282 if (shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {1283 parentComponent.ctx.deactivate(vnode);1284 return;1285 }1286 const shouldInvokeDirs = shapeFlag & 1 /* ELEMENT */ && dirs;1287 let vnodeHook;1288 if ((vnodeHook = props && props.onVnodeBeforeUnmount)) {1289 invokeVNodeHook(vnodeHook, parentComponent, vnode);1290 }1291 if (shapeFlag & 6 /* COMPONENT */) {1292 unmountComponent(vnode.component, parentSuspense, doRemove);1293 }1294 else {1295 if ( shapeFlag & 128 /* SUSPENSE */) {1296 vnode.suspense.unmount(parentSuspense, doRemove);1297 return;1298 }1299 if (shouldInvokeDirs) {1300 invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount');1301 }1302 if (dynamicChildren &&1303 // #1153: fast path should not be taken for non-stable (v-for) fragments1304 (type !== Fragment ||1305 (patchFlag > 0 && patchFlag & 64 /* STABLE_FRAGMENT */))) {1306 // fast path for block nodes: only need to unmount dynamic children.1307 unmountChildren(dynamicChildren, parentComponent, parentSuspense);1308 }1309 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1310 unmountChildren(children, parentComponent, parentSuspense);1311 }1312 // an unmounted teleport should always remove its children1313 if (shapeFlag & 64 /* TELEPORT */) {1314 vnode.type.remove(vnode, internals);1315 }1316 if (doRemove) {1317 remove(vnode);1318 }1319 }1320 if ((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) {1321 queuePostRenderEffect(() => {1322 vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);1323 shouldInvokeDirs &&1324 invokeDirectiveHook(vnode, null, parentComponent, 'unmounted');1325 }, parentSuspense);1326 }1327 };1328 const remove = vnode => {1329 const { type, el, anchor, transition } = vnode;1330 if (type === Fragment) {1331 removeFragment(el, anchor);1332 return;1333 }1334 if ( type === Static) {1335 removeStaticNode(vnode);1336 return;1337 }1338 const performRemove = () => {1339 hostRemove(el);1340 if (transition && !transition.persisted && transition.afterLeave) {1341 transition.afterLeave();1342 }1343 };1344 if (vnode.shapeFlag & 1 /* ELEMENT */ &&1345 transition &&1346 !transition.persisted) {1347 const { leave, delayLeave } = transition;1348 const performLeave = () => leave(el, performRemove);1349 if (delayLeave) {1350 delayLeave(vnode.el, performRemove, performLeave);1351 }1352 else {1353 performLeave();1354 }1355 }1356 else {1357 performRemove();1358 }1359 };1360 const removeFragment = (cur, end) => {1361 // For fragments, directly remove all contained DOM nodes.1362 // (fragment child nodes cannot have transition)1363 let next;1364 while (cur !== end) {1365 next = hostNextSibling(cur);1366 hostRemove(cur);1367 cur = next;1368 }1369 hostRemove(end);1370 };1371 const unmountComponent = (instance, parentSuspense, doRemove) => {1372 if ( instance.type.__hmrId) {1373 unregisterHMR(instance);1374 }1375 const { bum, effects, update, subTree, um } = instance;1376 // beforeUnmount hook1377 if (bum) {1378 invokeArrayFns(bum);1379 }1380 if (effects) {1381 for (let i = 0; i < effects.length; i++) {1382 stop(effects[i]);1383 }1384 }1385 // update may be null if a component is unmounted before its async1386 // setup has resolved.1387 if (update) {1388 stop(update);1389 unmount(subTree, instance, parentSuspense, doRemove);1390 }1391 // unmounted hook1392 if (um) {1393 queuePostRenderEffect(um, parentSuspense);1394 }1395 queuePostRenderEffect(() => {1396 instance.isUnmounted = true;1397 }, parentSuspense);1398 // A component with async dep inside a pending suspense is unmounted before1399 // its async dep resolves. This should remove the dep from the suspense, and1400 // cause the suspense to resolve immediately if that was the last dep.1401 if (1402 parentSuspense &&1403 parentSuspense.pendingBranch &&1404 !parentSuspense.isUnmounted &&1405 instance.asyncDep &&1406 !instance.asyncResolved &&1407 instance.suspenseId === parentSuspense.pendingId) {1408 parentSuspense.deps--;1409 if (parentSuspense.deps === 0) {1410 parentSuspense.resolve();1411 }1412 }1413 {1414 devtoolsComponentRemoved(instance);1415 }1416 };1417 const unmountChildren = (children, parentComponent, parentSuspense, doRemove = false, start = 0) => {1418 for (let i = start; i < children.length; i++) {1419 unmount(children[i], parentComponent, parentSuspense, doRemove);1420 }1421 };1422 const getNextHostNode = vnode => {1423 if (vnode.shapeFlag & 6 /* COMPONENT */) {1424 return getNextHostNode(vnode.component.subTree);1425 }1426 if ( vnode.shapeFlag & 128 /* SUSPENSE */) {1427 return vnode.suspense.next();1428 }1429 return hostNextSibling((vnode.anchor || vnode.el));1430 };1431 /**1432 * #11561433 * When a component is HMR-enabled, we need to make sure that all static nodes1434 * inside a block also inherit the DOM element from the previous tree so that1435 * HMR updates (which are full updates) can retrieve the element for patching.1436 *1437 * #20801438 * Inside keyed `template` fragment static children, if a fragment is moved,1439 * the children will always moved so that need inherit el form previous nodes1440 * to ensure correct moved position.1441 */1442 const traverseStaticChildren = (n1, n2, shallow = false) => {1443 const ch1 = n1.children;1444 const ch2 = n2.children;1445 if (isArray(ch1) && isArray(ch2)) {1446 for (let i = 0; i < ch1.length; i++) {1447 // this is only called in the optimized path so array children are1448 // guaranteed to be vnodes1449 const c1 = ch1[i];1450 const c2 = (ch2[i] = cloneIfMounted(ch2[i]));1451 if (c2.shapeFlag & 1 /* ELEMENT */ && !c2.dynamicChildren) {1452 if (c2.patchFlag <= 0 || c2.patchFlag === 32 /* HYDRATE_EVENTS */) {1453 c2.el = c1.el;1454 }1455 if (!shallow)1456 traverseStaticChildren(c1, c2);1457 }1458 if ( c2.type === Comment) {1459 c2.el = c1.el;1460 }1461 }1462 }1463 };1464 const render = (vnode, container) => {1465 if (vnode == null) {1466 if (container._vnode) {1467 unmount(container._vnode, null, null, true);1468 }1469 }1470 else {1471 patch(container._vnode || null, vnode, container);1472 }1473 flushPostFlushCbs();1474 container._vnode = vnode;1475 };1476 const internals = {1477 p: patch,1478 um: unmount,1479 m: move,1480 r: remove,1481 mt: mountComponent,1482 mc: mountChildren,1483 pc: patchChildren,1484 pbc: patchBlockChildren,1485 n: getNextHostNode,1486 o: options1487 };1488 let hydrate;1489 let hydrateNode;1490 if (createHydrationFns) {1491 [hydrate, hydrateNode] = createHydrationFns(internals);1492 }1493 return {1494 render,1495 hydrate,1496 createApp: createAppAPI(render, hydrate)1497 };1498}1499// render.render 62451500const render = (vnode, container) => {1501 if (vnode == null) {1502 if (container._vnode) {1503 unmount(container._vnode, null, null, true);1504 }1505 }1506 else {1507 patch(container._vnode || null, vnode, container);1508 }1509 flushPostFlushCbs();1510 container._vnode = vnode;1511};1512/**1513 * render 62451514 * 1. unmount(container._vnode, null, null, true);1515 * 2. patch(container._vnode || null, vnode, container);1516 * 3. flushPostFlushCbs();1517 */1518 // patch 51101519 const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) => {1520 // patching & not same type, unmount old tree1521 if (n1 && !isSameVNodeType(n1, n2)) {1522 anchor = getNextHostNode(n1);1523 unmount(n1, parentComponent, parentSuspense, true);1524 n1 = null;1525 }1526 if (n2.patchFlag === -2 /* BAIL */) {1527 optimized = false;1528 n2.dynamicChildren = null;1529 }1530 const { type, ref, shapeFlag } = n2;1531 switch (type) {1532 case Text:1533 processText(n1, n2, container, anchor);1534 break;1535 case Comment:1536 processCommentNode(n1, n2, container, anchor);1537 break;1538 case Static:1539 if (n1 == null) {1540 mountStaticNode(n2, container, anchor, isSVG);1541 }1542 else {1543 patchStaticNode(n1, n2, container, isSVG);1544 }1545 break;1546 case Fragment:1547 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1548 break;1549 default:1550 if (shapeFlag & 1 /* ELEMENT */) {1551 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1552 }1553 else if (shapeFlag & 6 /* COMPONENT */) {1554 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1555 }1556 else if (shapeFlag & 64 /* TELEPORT */) {1557 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);1558 }1559 else if ( shapeFlag & 128 /* SUSPENSE */) {1560 type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);1561 }1562 else {1563 warn('Invalid VNode type:', type, `(${typeof type})`);1564 }1565 }1566 // set ref1567 if (ref != null && parentComponent) {1568 setRef(ref, n1 && n1.ref, parentComponent, parentSuspense, n2);1569 }1570};1571function isSameVNodeType(n1, n2) {1572 if (1573 n2.shapeFlag & 6 /* COMPONENT */ &&1574 hmrDirtyComponents.has(n2.type)) {1575 // HMR only: if the component has been hot-updated, force a reload.1576 return false;1577 }1578 return n1.type === n2.type && n1.key === n2.key;1579}1580const processComponent = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {1581 if (n1 == null) {1582 if (n2.shapeFlag & 512 /* COMPONENT_KEPT_ALIVE */) {1583 parentComponent.ctx.activate(n2, container, anchor, isSVG, optimized);1584 }1585 else {1586 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1587 }1588 }1589 else {1590 updateComponent(n1, n2, optimized);1591 }1592};1593const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {1594 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent, parentSuspense));1595 if ( instance.type.__hmrId) {1596 registerHMR(instance);1597 }1598 {1599 pushWarningContext(initialVNode);1600 startMeasure(instance, `mount`);1601 }1602 // inject renderer internals for keepAlive1603 if (isKeepAlive(initialVNode)) {1604 instance.ctx.renderer = internals;1605 }1606 // resolve props and slots for setup context1607 {1608 startMeasure(instance, `init`);1609 }1610 setupComponent(instance);1611 {1612 endMeasure(instance, `init`);1613 }1614 // setup() is async. This component relies on async logic to be resolved1615 // before proceeding1616 if ( instance.asyncDep) {1617 parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect);1618 // Give it a placeholder if this is not hydration1619 // TODO handle self-defined fallback1620 if (!initialVNode.el) {1621 const placeholder = (instance.subTree = createVNode(Comment));1622 processCommentNode(null, placeholder, container, anchor);1623 }1624 return;1625 }1626 setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized);1627 {1628 popWarningContext();1629 endMeasure(instance, `mount`);1630 }1631};1632function createComponentInstance(vnode, parent, suspense) {1633 const type = vnode.type;1634 // inherit parent app context - or - if root, adopt from root vnode1635 const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext;1636 const instance = {1637 uid: uid$2++,1638 vnode,1639 type,1640 parent,1641 appContext,1642 root: null,1643 next: null,1644 subTree: null,1645 update: null,1646 render: null,1647 proxy: null,1648 withProxy: null,1649 effects: null,1650 provides: parent ? parent.provides : Object.create(appContext.provides),1651 accessCache: null,1652 renderCache: [],1653 // local resovled assets1654 components: null,1655 directives: null,1656 // resolved props and emits options1657 propsOptions: normalizePropsOptions(type, appContext),1658 emitsOptions: normalizeEmitsOptions(type, appContext),1659 // emit1660 emit: null,1661 emitted: null,1662 // state1663 ctx: EMPTY_OBJ,1664 data: EMPTY_OBJ,1665 props: EMPTY_OBJ,1666 attrs: EMPTY_OBJ,1667 slots: EMPTY_OBJ,1668 refs: EMPTY_OBJ,1669 setupState: EMPTY_OBJ,1670 setupContext: null,1671 // suspense related1672 suspense,1673 suspenseId: suspense ? suspense.pendingId : 0,1674 asyncDep: null,1675 asyncResolved: false,1676 // lifecycle hooks1677 // not using enums here because it results in computed properties1678 isMounted: false,1679 isUnmounted: false,1680 isDeactivated: false,1681 bc: null,1682 c: null,1683 bm: null,1684 m: null,1685 bu: null,1686 u: null,1687 um: null,1688 bum: null,1689 da: null,1690 a: null,1691 rtg: null,1692 rtc: null,1693 ec: null1694 };1695 {1696 instance.ctx = createRenderContext(instance);1697 }1698 instance.root = parent ? parent.root : instance;1699 instance.emit = emit.bind(null, instance);1700 {1701 devtoolsComponentAdded(instance);1702 }1703 return instance;1704}1705// In dev mode, the proxy target exposes the same properties as seen on `this`1706// for easier console inspection. In prod mode it will be an empty object so1707// these properties definitions can be skipped.1708const publicPropertiesMap = extend(Object.create(null), {1709 $: i => i,1710 $el: i => i.vnode.el,1711 $data: i => i.data,1712 $props: i => ( shallowReadonly(i.props) ),1713 $attrs: i => ( shallowReadonly(i.attrs) ),1714 $slots: i => ( shallowReadonly(i.slots) ),1715 $refs: i => ( shallowReadonly(i.refs) ),1716 $parent: i => i.parent && i.parent.proxy,1717 $root: i => i.root && i.root.proxy,1718 $emit: i => i.emit,1719 $options: i => ( resolveMergedOptions(i) ),1720 $forceUpdate: i => () => queueJob(i.update),1721 $nextTick: () => nextTick,1722 $watch: i => ( instanceWatch.bind(i) )1723});1724function createRenderContext(instance) {1725 const target = {};1726 // expose internal instance for proxy handlers1727 Object.defineProperty(target, `_`, {1728 configurable: true,1729 enumerable: false,1730 get: () => instance1731 });1732 // expose public properties1733 Object.keys(publicPropertiesMap).forEach(key => {1734 Object.defineProperty(target, key, {1735 configurable: true,1736 enumerable: false,1737 get: () => publicPropertiesMap[key](instance),1738 // intercepted by the proxy so no need for implementation,1739 // but needed to prevent set errors1740 set: NOOP1741 });1742 });1743 // expose global properties1744 const { globalProperties } = instance.appContext.config;1745 Object.keys(globalProperties).forEach(key => {1746 Object.defineProperty(target, key, {1747 configurable: true,1748 enumerable: false,1749 get: () => globalProperties[key],1750 set: NOOP1751 });1752 });1753 return target;1754}1755function emit(instance, event, ...args) {1756 const props = instance.vnode.props || EMPTY_OBJ;1757 {1758 const { emitsOptions, propsOptions: [propsOptions] } = instance;1759 if (emitsOptions) {1760 if (!(event in emitsOptions)) {1761 if (!propsOptions || !(`on` + capitalize(event) in propsOptions)) {1762 warn(`Component emitted event "${event}" but it is neither declared in ` +1763 `the emits option nor as an "on${capitalize(event)}" prop.`);1764 }1765 }1766 else {1767 const validator = emitsOptions[event];1768 if (isFunction(validator)) {1769 const isValid = validator(...args);1770 if (!isValid) {1771 warn(`Invalid event arguments: event validation failed for event "${event}".`);1772 }1773 }1774 }1775 }1776 }1777 {1778 devtoolsComponentEmit(instance, event, args);1779 }1780 let handlerName = `on${capitalize(event)}`;1781 let handler = props[handlerName];1782 // for v-model update:xxx events, also trigger kebab-case equivalent1783 // for props passed via kebab-case1784 if (!handler && event.startsWith('update:')) {1785 handlerName = `on${capitalize(hyphenate(event))}`;1786 handler = props[handlerName];1787 }1788 if (!handler) {1789 handler = props[handlerName + `Once`];1790 if (!instance.emitted) {1791 (instance.emitted = {})[handlerName] = true;1792 }1793 else if (instance.emitted[handlerName]) {1794 return;1795 }1796 }1797 if (handler) {1798 callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args);1799 }1800}1801function setupComponent(instance, isSSR = false) {1802 isInSSRComponentSetup = isSSR;1803 const { props, children, shapeFlag } = instance.vnode;1804 const isStateful = shapeFlag & 4 /* STATEFUL_COMPONENT */;1805 initProps(instance, props, isStateful, isSSR);1806 initSlots(instance, children);1807 const setupResult = isStateful1808 ? setupStatefulComponent(instance, isSSR)1809 : undefined;1810 isInSSRComponentSetup = false;1811 return setupResult;1812}1813/**1814 * åå§åprops1815 * @param {*} instance 1816 * @param {*} rawProps 1817 * @param {*} isStateful 1818 * @param {*} isSSR 1819 */1820function initProps(instance, rawProps, isStateful, // result of bitwise flag comparison1821 isSSR = false) {1822 const props = {};1823 const attrs = {};1824 def(attrs, InternalObjectKey, 1);1825 setFullProps(instance, rawProps, props, attrs);1826 // validation1827 {1828 validateProps(props, instance);1829 }1830 if (isStateful) {1831 // stateful1832 instance.props = isSSR ? props : shallowReactive(props);1833 }1834 else {1835 if (!instance.type.props) {1836 // functional w/ optional props, props === attrs1837 instance.props = attrs;1838 }1839 else {1840 // functional w/ declared props1841 instance.props = props;1842 }1843 }1844 instance.attrs = attrs;1845}1846function setFullProps(instance, rawProps, props, attrs) {1847 const [options, needCastKeys] = instance.propsOptions;1848 if (rawProps) {1849 for (const key in rawProps) {1850 const value = rawProps[key];1851 // key, ref are reserved and never passed down1852 if (isReservedProp(key)) {1853 continue;1854 }1855 // prop option names are camelized during normalization, so to support1856 // kebab -> camel conversion here we need to camelize the key.1857 let camelKey;1858 if (options && hasOwn(options, (camelKey = camelize(key)))) {1859 props[camelKey] = value;1860 }1861 else if (!isEmitListener(instance.emitsOptions, key)) {1862 // Any non-declared (either as a prop or an emitted event) props are put1863 // into a separate `attrs` object for spreading. Make sure to preserve1864 // original key casing1865 attrs[key] = value;1866 }1867 }1868 }1869 if (needCastKeys) {1870 const rawCurrentProps = toRaw(props);1871 for (let i = 0; i < needCastKeys.length; i++) {1872 const key = needCastKeys[i];1873 props[key] = resolvePropValue(options, rawCurrentProps, key, rawCurrentProps[key], instance);1874 }1875 }1876}1877function resolvePropValue(options, props, key, value, instance) {1878 const opt = options[key];1879 if (opt != null) {1880 const hasDefault = hasOwn(opt, 'default');1881 // default values1882 if (hasDefault && value === undefined) {1883 const defaultValue = opt.default;1884 if (opt.type !== Function && isFunction(defaultValue)) {1885 setCurrentInstance(instance);1886 value = defaultValue(props);1887 setCurrentInstance(null);1888 }1889 else {1890 value = defaultValue;1891 }1892 }1893 // boolean casting1894 if (opt[0 /* shouldCast */]) {1895 if (!hasOwn(props, key) && !hasDefault) {1896 value = false;1897 }1898 else if (opt[1 /* shouldCastTrue */] &&1899 (value === '' || value === hyphenate(key))) {1900 value = true;1901 }1902 }1903 }1904 return value;1905}1906function normalizePropsOptions(comp, appContext, asMixin = false) {1907 const appId = appContext.app ? appContext.app._uid : -1;1908 const cache = comp.__props || (comp.__props = {});1909 const cached = cache[appId];1910 if (cached) {1911 return cached;1912 }1913 const raw = comp.props;1914 const normalized = {};1915 const needCastKeys = [];1916 // apply mixin/extends props1917 let hasExtends = false;1918 if ( !isFunction(comp)) {1919 const extendProps = (raw) => {1920 hasExtends = true;1921 const [props, keys] = normalizePropsOptions(raw, appContext, true);1922 extend(normalized, props);1923 if (keys)1924 needCastKeys.push(...keys);1925 };1926 if (!asMixin && appContext.mixins.length) {1927 appContext.mixins.forEach(extendProps);1928 }1929 if (comp.extends) {1930 extendProps(comp.extends);1931 }1932 if (comp.mixins) {1933 comp.mixins.forEach(extendProps);1934 }1935 }1936 if (!raw && !hasExtends) {1937 return (cache[appId] = EMPTY_ARR);1938 }1939 if (isArray(raw)) {1940 for (let i = 0; i < raw.length; i++) {1941 if ( !isString(raw[i])) {1942 warn(`props must be strings when using array syntax.`, raw[i]);1943 }1944 const normalizedKey = camelize(raw[i]);1945 if (validatePropName(normalizedKey)) {1946 normalized[normalizedKey] = EMPTY_OBJ;1947 }1948 }1949 }1950 else if (raw) {1951 if ( !isObject(raw)) {1952 warn(`invalid props options`, raw);1953 }1954 for (const key in raw) {1955 const normalizedKey = camelize(key);1956 if (validatePropName(normalizedKey)) {1957 const opt = raw[key];1958 const prop = (normalized[normalizedKey] =1959 isArray(opt) || isFunction(opt) ? { type: opt } : opt);1960 if (prop) {1961 const booleanIndex = getTypeIndex(Boolean, prop.type);1962 const stringIndex = getTypeIndex(String, prop.type);1963 prop[0 /* shouldCast */] = booleanIndex > -1;1964 prop[1 /* shouldCastTrue */] =1965 stringIndex < 0 || booleanIndex < stringIndex;1966 // if the prop needs boolean casting or default value1967 if (booleanIndex > -1 || hasOwn(prop, 'default')) {1968 needCastKeys.push(normalizedKey);1969 }1970 }1971 }1972 }1973 }1974 return (cache[appId] = [normalized, needCastKeys]);1975}1976const initSlots = (instance, children) => {1977 if (instance.vnode.shapeFlag & 32 /* SLOTS_CHILDREN */) {1978 const type = children._;1979 if (type) {1980 instance.slots = children;1981 // make compiler marker non-enumerable1982 def(children, '_', type);1983 }1984 else {1985 normalizeObjectSlots(children, (instance.slots = {}));1986 }1987 }1988 else {1989 instance.slots = {};1990 if (children) {1991 normalizeVNodeSlots(instance, children);1992 }1993 }1994 def(instance.slots, InternalObjectKey, 1);1995};1996function setupStatefulComponent(instance, isSSR) {1997 const Component = instance.type;1998 {1999 if (Component.name) {2000 validateComponentName(Component.name, instance.appContext.config);2001 }2002 if (Component.components) {2003 const names = Object.keys(Component.components);2004 for (let i = 0; i < names.length; i++) {2005 validateComponentName(names[i], instance.appContext.config);2006 }2007 }2008 if (Component.directives) {2009 const names = Object.keys(Component.directives);2010 for (let i = 0; i < names.length; i++) {2011 validateDirectiveName(names[i]);2012 }2013 }2014 }2015 // 0. create render proxy property access cache2016 instance.accessCache = {};2017 // 1. create public instance / render proxy2018 // also mark it raw so it's never observed2019 instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers);2020 {2021 exposePropsOnRenderContext(instance);2022 }2023 // 2. call setup()2024 const { setup } = Component;2025 if (setup) {2026 const setupContext = (instance.setupContext =2027 setup.length > 1 ? createSetupContext(instance) : null);2028 currentInstance = instance;2029 pauseTracking();2030 const setupResult = callWithErrorHandling(setup, instance, 0 /* SETUP_FUNCTION */, [ shallowReadonly(instance.props) , setupContext]);2031 resetTracking();2032 currentInstance = null;2033 if (isPromise(setupResult)) {2034 if (isSSR) {2035 // return the promise so server-renderer can wait on it2036 return setupResult.then((resolvedResult) => {2037 handleSetupResult(instance, resolvedResult);2038 });2039 }2040 else {2041 // async setup returned Promise.2042 // bail here and wait for re-entry.2043 instance.asyncDep = setupResult;2044 }2045 }2046 else {2047 handleSetupResult(instance, setupResult);2048 }2049 }2050 else {2051 finishComponentSetup(instance);2052 }2053}2054/**2055 * åå§åslot2056 * 2057 */2058const initSlots = (instance, children) => {2059 if (instance.vnode.shapeFlag & 32 /* SLOTS_CHILDREN */) {2060 const type = children._;2061 if (type) {2062 instance.slots = children;2063 // make compiler marker non-enumerable2064 def(children, '_', type);2065 }2066 else {2067 normalizeObjectSlots(children, (instance.slots = {}));2068 }2069 }2070 else {2071 instance.slots = {};2072 if (children) {2073 normalizeVNodeSlots(instance, children);2074 }2075 }2076 def(instance.slots, InternalObjectKey, 1);2077};2078const normalizeObjectSlots = (rawSlots, slots) => {2079 const ctx = rawSlots._ctx;2080 for (const key in rawSlots) {2081 if (isInternalKey(key))2082 continue;2083 const value = rawSlots[key];2084 if (isFunction(value)) {2085 slots[key] = normalizeSlot(key, value, ctx);2086 }2087 else if (value != null) {2088 {2089 warn(`Non-function value encountered for slot "${key}". ` +2090 `Prefer function slots for better performance.`);2091 }2092 const normalized = normalizeSlotValue(value);2093 slots[key] = () => normalized;2094 }2095 }2096};2097const normalizeVNodeSlots = (instance, children) => {2098 if ( !isKeepAlive(instance.vnode)) {2099 warn(`Non-function value encountered for default slot. ` +2100 `Prefer function slots for better performance.`);2101 }2102 const normalized = normalizeSlotValue(children);2103 instance.slots.default = () => normalized;2104};2105const normalizeSlotValue = (value) => isArray(value)2106 ? value.map(normalizeVNode)2107 : [normalizeVNode(value)];2108const normalizeSlot = (key, rawSlot, ctx) => withCtx((props) => {2109 if ( currentInstance) {2110 warn(`Slot "${key}" invoked outside of the render function: ` +2111 `this will not track dependencies used in the slot. ` +2112 `Invoke the slot function inside the render function instead.`);2113 }2114 return normalizeSlotValue(rawSlot(props));2115}, ctx);2116function normalizeVNode(child) {2117 if (child == null || typeof child === 'boolean') {2118 // empty placeholder2119 return createVNode(Comment);2120 }2121 else if (isArray(child)) {2122 // fragment2123 return createVNode(Fragment, null, child);2124 }2125 else if (typeof child === 'object') {2126 // already vnode, this should be the most common since compiled templates2127 // always produce all-vnode children arrays2128 return child.el === null ? child : cloneVNode(child);2129 }2130 else {2131 // strings and numbers2132 return createVNode(Text, null, String(child));2133 }2134}2135/**2136 * setupStatefulComponent2137 */2138function setupStatefulComponent(instance, isSSR) {2139 const Component = instance.type;2140 {2141 if (Component.name) {2142 validateComponentName(Component.name, instance.appContext.config);2143 }2144 if (Component.components) {2145 const names = Object.keys(Component.components);2146 for (let i = 0; i < names.length; i++) {2147 validateComponentName(names[i], instance.appContext.config);2148 }2149 }2150 if (Component.directives) {2151 const names = Object.keys(Component.directives);2152 for (let i = 0; i < names.length; i++) {2153 validateDirectiveName(names[i]);2154 }2155 }2156 }2157 // 0. create render proxy property access cache2158 instance.accessCache = {};2159 // 1. create public instance / render proxy2160 // also mark it raw so it's never observed2161 instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers);2162 {2163 exposePropsOnRenderContext(instance);2164 }2165 // 2. call setup()2166 const { setup } = Component;2167 if (setup) {...
setup.js
Source:setup.js
...150 }151 if (Component.directives) {152 const names = Object.keys(Component.directives);153 for (let i = 0; i < names.length; i++) {154 validateDirectiveName(names[i]);155 }156 }157 }158 // 0. create render proxy property access cache159 instance.accessCache = {};160 // 1. create public instance / render proxy161 // also mark it raw so it's never observed162 instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers);163 {164 exposePropsOnRenderContext(instance);165 }166 // 2. call setup()167 const { setup } = Component;168 if (setup) {...
directives.js
Source:directives.js
...4 _component: rootComponent,5 _props: rootProps,6 directive(name, directive) {7 if ((process.env.NODE_ENV !== 'production')) {8 validateDirectiveName(name)9 }10 if (!directive) {11 // 没æ第äºä¸ªåæ°ï¼åè·å对åºçæ令对象12 return context.directives[name]13 }14 if ((process.env.NODE_ENV !== 'production') && context.directives[name]) {15 // éå¤æ³¨åçè¦å16 warn(`Directive "${name}" has already been registered in target app.`)17 }18 context.directives[name] = directive19 return app20 }21 }22 return app...
loadDirectives.js
Source:loadDirectives.js
...15 state.typeDefs.push(loadGraphqlFile(path.join(root, 'type.graphql')));16};17const insertIntoSchema = (state, root, dirent) => {18 if (dirent.name === 'type.graphql') return;19 if (dirent.isFile() && validateDirectiveName(dirent.name))20 return (state.directives[basename(dirent.name)] = path.join(21 root,22 dirent.name,23 ));24};25const validateDirectiveName = (name) =>26 isCamelCase(basename(name)) && path.extname(name) === '.js';...
Using AI Code Generation
1const { validateDirectiveName } = require('@playwright/test/lib/server/frames');2validateDirectiveName('script-src');3validateDirectiveName('style-src');4validateDirectiveName('worker-src');5validateDirectiveName('default-src');6validateDirectiveName('img-src');7validateDirectiveName('font-src');8validateDirectiveName('connect-src');9validateDirectiveName('frame-src');10validateDirectiveName('manifest-src');11validateDirectiveName('media-src');12validateDirectiveName('object-src');13validateDirectiveName('prefetch-src');14validateDirectiveName('report-uri');15validateDirectiveName('sandbox');16validateDirectiveName('upgrade-insecure-requests');17validateDirectiveName('base-uri');18validateDirectiveName('form-action');19validateDirectiveName('frame-ancestors');20validateDirectiveName('navigate-to');21validateDirectiveName('plugin-types');22validateDirectiveName('require-sri-for');23validateDirectiveName('trusted-types');24validateDirectiveName('worker-src');25validateDirectiveName('block-all-mixed-content');26validateDirectiveName('referrer');27validateDirectiveName('report-to');28validateDirectiveName('require-trusted-types-for');29validateDirectiveName('disown-opener');30validateDirectiveName('child-src');31validateDirectiveName('worker-src');32const { validateHeaderName } = require('@playwright/test/lib/server/network');33validateHeaderName('accept');34validateHeaderName('accept-charset');35validateHeaderName('accept-encoding');36validateHeaderName('accept-language');37validateHeaderName('accept-datetime');38validateHeaderName('authorization');39validateHeaderName('cache-control');40validateHeaderName('connection');41validateHeaderName('cookie');42validateHeaderName('content-length');43validateHeaderName('content-md5');44validateHeaderName('content-type');45validateHeaderName('date');46validateHeaderName('expect');47validateHeaderName('forwarded');48validateHeaderName('from');49validateHeaderName('host');50validateHeaderName('if-match');51validateHeaderName('if-modified-since');52validateHeaderName('if-none-match');53validateHeaderName('if-range');54validateHeaderName('if-unmodified-since');55validateHeaderName('max-forwards');56validateHeaderName('origin');57validateHeaderName('pragma');58validateHeaderName('proxy-authorization');59validateHeaderName('range');60validateHeaderName('referer');61validateHeaderName('te');62validateHeaderName('user-agent');63validateHeaderName('upgrade');
Using AI Code Generation
1const { validateDirectiveName } = require('playwright/lib/utils/validation');2const { expect } = require('chai');3describe('validateDirectiveName', function () {4 it('should throw error if directive name is not valid', function () {5 expect(() => validateDirectiveName('test')).to.throw();6 });7 it('should not throw error if directive name is valid', function () {8 expect(() => validateDirectiveName('playwright:browser')).to.not.throw();9 });10});11module.exports = {12 use: {13 viewport: { width: 1280, height: 720 },14 {15 },16 },17};18const { setConfig } = require('playwright/lib/utils/config');19setConfig({20 use: {21 viewport: { width: 1280, height: 720 },22 {23 },24 },25});26import { PlaywrightTestConfig } from '@playwright/test';27const config: PlaywrightTestConfig = {28 use: {29 viewport: { width: 1280, height: 720 },30 {31 },32 },33};34export default config;35import { setConfig } from '@playwright/test';36setConfig({37 use: {38 viewport: { width: 1280, height: 720 },39 {40 },41 },42});43module.exports = {44 use: {45 viewport: { width: 1280, height: 720 },46 {
Using AI Code Generation
1const { validateDirectiveName } = require('@playwright/internal');2const directiveNames = ['@foo', '@bar', '@baz'];3directiveNames.forEach(name => {4 try {5 validateDirectiveName(name);6 } catch (error) {7 console.log(`Error while validating directive name ${name} : ${error}`);8 }9});
Using AI Code Generation
1const { validateDirectiveName } = require('playwright/lib/utils/utils');2const directiveName = 'testDirective';3const directiveNameValidation = validateDirectiveName(directiveName);4console.log(directiveNameValidation);5const page = require('@playwright/test').page;6page.addDirective('testDirective', async function (element, value) {7 await element.fill(value);8});9module.exports = {10};11const { test } = require('@playwright/test');12const google = require('../page-objects/google');13test('test to use directive in the page object', async ({ page }) => {14 await page.testDirective(google.googleSearchBox, 'Playwright');15 await page.click(google.googleSearchButton);16});17 ✓ test to use directive in the page object (1s)18 1 passed (1s)19const { test } = require('@playwright/test');20const google = require('../page-objects/google');21test.addDirective('testDirective', async function (element, value) {22 await element.fill(value);23});24test('test to use directive in the test file', async ({ page }) => {
Using AI Code Generation
1const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');2const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');3const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');4const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');5const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');6const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');7const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');8const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');9const { validateDirectiveName } = require('@playwright/test/lib/server/trace/common/traceModel');
Using AI Code Generation
1const { validateDirectiveName } = require('playwright/lib/utils/validator');2validateDirectiveName('test');3 at validateDirectiveName (C:\Users\user\Documents\playwright\playwright\lib\utils\validator.js:12:11)4 at Object.<anonymous> (C:\Users\user\Documents\playwright\playwright\test.js:4:1)5 at Module._compile (internal/modules/cjs/loader.js:1137:30)6 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)7 at Module.load (internal/modules/cjs/loader.js:985:32)8 at Function.Module._load (internal/modules/cjs/loader.js:878:14)9 at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
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.
Get 100 minutes of automation test minutes FREE!!