Best JavaScript code snippet using playwright-internal
runtime-test.global.js
Source:runtime-test.global.js
...1860 fallback: normalizeVNode(null)1861 };1862 }1863 }1864 function createDevEffectOptions(instance) {1865 return {1866 scheduler: queueJob,1867 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1868 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01869 };1870 }1871 function isSameType$1(n1, n2) {1872 return n1.type === n2.type && n1.key === n2.key;1873 }1874 function invokeHooks(hooks, arg) {1875 for (let i = 0; i < hooks.length; i++) {1876 hooks[i](arg);1877 }1878 }1879 function queuePostRenderEffect(fn, suspense) {1880 if (suspense !== null && !suspense.isResolved) {1881 if (isArray(fn)) {1882 suspense.effects.push(...fn);1883 }1884 else {1885 suspense.effects.push(fn);1886 }1887 }1888 else {1889 queuePostFlushCb(fn);1890 }1891 }1892 /**1893 * The createRenderer function accepts two generic arguments:1894 * HostNode and HostElement, corresponding to Node and Element types in the1895 * host environment. For example, for runtime-dom, HostNode would be the DOM1896 * `Node` interface and HostElement would be the DOM `Element` interface.1897 *1898 * Custom renderers can pass in the platform specific types like this:1899 *1900 * ``` js1901 * const { render, createApp } = createRenderer<Node, Element>({1902 * patchProp,1903 * ...nodeOps1904 * })1905 * ```1906 */1907 function createRenderer(options) {1908 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1909 function patch(n1, // null means this is a mount1910 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1911 // patching & not same type, unmount old tree1912 if (n1 != null && !isSameType$1(n1, n2)) {1913 anchor = getNextHostNode(n1);1914 unmount(n1, parentComponent, parentSuspense, true);1915 n1 = null;1916 }1917 const { type, shapeFlag } = n2;1918 switch (type) {1919 case Text:1920 processText(n1, n2, container, anchor);1921 break;1922 case Comment:1923 processCommentNode(n1, n2, container, anchor);1924 break;1925 case Fragment:1926 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1927 break;1928 case Portal:1929 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1930 break;1931 case Suspense:1932 {1933 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1934 }1935 break;1936 default:1937 if (shapeFlag & 1 /* ELEMENT */) {1938 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1939 }1940 else if (shapeFlag & 6 /* COMPONENT */) {1941 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1942 }1943 else {1944 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1945 }1946 }1947 }1948 function processText(n1, n2, container, anchor) {1949 if (n1 == null) {1950 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1951 }1952 else {1953 const el = (n2.el = n1.el);1954 if (n2.children !== n1.children) {1955 hostSetText(el, n2.children);1956 }1957 }1958 }1959 function processCommentNode(n1, n2, container, anchor) {1960 if (n1 == null) {1961 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1962 }1963 else {1964 // there's no support for dynamic comments1965 n2.el = n1.el;1966 }1967 }1968 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1969 if (n1 == null) {1970 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG);1971 }1972 else {1973 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1974 }1975 if (n2.ref !== null && parentComponent !== null) {1976 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1977 }1978 }1979 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG) {1980 const tag = vnode.type;1981 isSVG = isSVG || tag === 'svg';1982 const el = (vnode.el = hostCreateElement(tag, isSVG));1983 const { props, shapeFlag } = vnode;1984 if (props != null) {1985 for (const key in props) {1986 if (isReservedProp(key))1987 continue;1988 hostPatchProp(el, key, props[key], null, isSVG);1989 }1990 if (props.vnodeBeforeMount != null) {1991 invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode);1992 }1993 }1994 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1995 hostSetElementText(el, vnode.children);1996 }1997 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1998 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG);1999 }2000 hostInsert(el, container, anchor);2001 if (props != null && props.vnodeMounted != null) {2002 queuePostRenderEffect(() => {2003 invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode);2004 }, parentSuspense);2005 }2006 }2007 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, start = 0) {2008 for (let i = start; i < children.length; i++) {2009 const child = (children[i] = normalizeVNode(children[i]));2010 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG);2011 }2012 }2013 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {2014 const el = (n2.el = n1.el);2015 const { patchFlag, dynamicChildren } = n2;2016 const oldProps = (n1 && n1.props) || EMPTY_OBJ;2017 const newProps = n2.props || EMPTY_OBJ;2018 if (newProps.vnodeBeforeUpdate != null) {2019 invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1);2020 }2021 if (patchFlag > 0) {2022 // the presence of a patchFlag means this element's render code was2023 // generated by the compiler and can take the fast path.2024 // in this path old node and new node are guaranteed to have the same shape2025 // (i.e. at the exact same position in the source template)2026 if (patchFlag & 16 /* FULL_PROPS */) {2027 // element props contain dynamic keys, full diff needed2028 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2029 }2030 else {2031 // class2032 // this flag is matched when the element has dynamic class bindings.2033 if (patchFlag & 2 /* CLASS */) {2034 if (oldProps.class !== newProps.class) {2035 hostPatchProp(el, 'class', newProps.class, null, isSVG);2036 }2037 }2038 // style2039 // this flag is matched when the element has dynamic style bindings2040 if (patchFlag & 4 /* STYLE */) {2041 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);2042 }2043 // props2044 // This flag is matched when the element has dynamic prop/attr bindings2045 // other than class and style. The keys of dynamic prop/attrs are saved for2046 // faster iteration.2047 // Note dynamic keys like :[foo]="bar" will cause this optimization to2048 // bail out and go through a full diff because we need to unset the old key2049 if (patchFlag & 8 /* PROPS */) {2050 // if the flag is present then dynamicProps must be non-null2051 const propsToUpdate = n2.dynamicProps;2052 for (let i = 0; i < propsToUpdate.length; i++) {2053 const key = propsToUpdate[i];2054 const prev = oldProps[key];2055 const next = newProps[key];2056 if (prev !== next) {2057 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);2058 }2059 }2060 }2061 }2062 // text2063 // This flag is matched when the element has only dynamic text children.2064 // this flag is terminal (i.e. skips children diffing).2065 if (patchFlag & 1 /* TEXT */) {2066 if (n1.children !== n2.children) {2067 hostSetElementText(el, n2.children);2068 }2069 return; // terminal2070 }2071 }2072 else if (!optimized) {2073 // unoptimized, full diff2074 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2075 }2076 if (dynamicChildren != null) {2077 // children fast path2078 const oldDynamicChildren = n1.dynamicChildren;2079 for (let i = 0; i < dynamicChildren.length; i++) {2080 patch(oldDynamicChildren[i], dynamicChildren[i], el, null, parentComponent, parentSuspense, isSVG, true);2081 }2082 }2083 else if (!optimized) {2084 // full diff2085 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);2086 }2087 if (newProps.vnodeUpdated != null) {2088 queuePostRenderEffect(() => {2089 invokeDirectiveHook(newProps.vnodeUpdated, parentComponent, n2, n1);2090 }, parentSuspense);2091 }2092 }2093 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {2094 if (oldProps !== newProps) {2095 for (const key in newProps) {2096 if (isReservedProp(key))2097 continue;2098 const next = newProps[key];2099 const prev = oldProps[key];2100 if (next !== prev) {2101 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2102 }2103 }2104 if (oldProps !== EMPTY_OBJ) {2105 for (const key in oldProps) {2106 if (isReservedProp(key))2107 continue;2108 if (!(key in newProps)) {2109 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2110 }2111 }2112 }2113 }2114 }2115 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2116 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));2117 const fragmentEndAnchor = (n2.anchor = n12118 ? n1.anchor2119 : hostCreateComment(''));2120 if (n1 == null) {2121 hostInsert(fragmentStartAnchor, container, anchor);2122 hostInsert(fragmentEndAnchor, container, anchor);2123 // a fragment can only have array children2124 // since they are either generated by the compiler, or implicitly created2125 // from arrays.2126 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG);2127 }2128 else {2129 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);2130 }2131 }2132 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2133 const targetSelector = n2.props && n2.props.target;2134 const { patchFlag, shapeFlag, children } = n2;2135 if (n1 == null) {2136 const target = (n2.target = isString(targetSelector)2137 ? hostQuerySelector(targetSelector)2138 : null);2139 if (target != null) {2140 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2141 hostSetElementText(target, children);2142 }2143 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2144 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG);2145 }2146 }2147 else {2148 warn('Invalid Portal target on mount:', target, `(${typeof target})`);2149 }2150 }2151 else {2152 // update content2153 const target = (n2.target = n1.target);2154 if (patchFlag === 1 /* TEXT */) {2155 hostSetElementText(target, children);2156 }2157 else if (!optimized) {2158 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);2159 }2160 // target changed2161 if (targetSelector !== (n1.props && n1.props.target)) {2162 const nextTarget = (n2.target = isString(targetSelector)2163 ? hostQuerySelector(targetSelector)2164 : null);2165 if (nextTarget != null) {2166 // move content2167 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2168 hostSetElementText(target, '');2169 hostSetElementText(nextTarget, children);2170 }2171 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2172 for (let i = 0; i < children.length; i++) {2173 move(children[i], nextTarget, null);2174 }2175 }2176 }2177 else {2178 warn('Invalid Portal target on update:', target, `(${typeof target})`);2179 }2180 }2181 }2182 // insert an empty node as the placeholder for the portal2183 processCommentNode(n1, n2, container, anchor);2184 }2185 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2186 if (n1 == null) {2187 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2188 }2189 else {2190 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);2191 }2192 }2193 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2194 const hiddenContainer = hostCreateElement('div');2195 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));2196 const { content, fallback } = normalizeSuspenseChildren(n2);2197 suspense.subTree = content;2198 suspense.fallbackTree = fallback;2199 // start mounting the content subtree in an off-dom container2200 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);2201 // now check if we have encountered any async deps2202 if (suspense.deps > 0) {2203 // mount the fallback tree2204 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context2205 isSVG, optimized);2206 n2.el = fallback.el;2207 }2208 else {2209 // Suspense has no async deps. Just resolve.2210 resolveSuspense(suspense);2211 }2212 }2213 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {2214 const suspense = (n2.suspense = n1.suspense);2215 suspense.vnode = n2;2216 const { content, fallback } = normalizeSuspenseChildren(n2);2217 const oldSubTree = suspense.subTree;2218 const oldFallbackTree = suspense.fallbackTree;2219 if (!suspense.isResolved) {2220 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);2221 if (suspense.deps > 0) {2222 // still pending. patch the fallback tree.2223 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context2224 isSVG, optimized);2225 n2.el = fallback.el;2226 }2227 // If deps somehow becomes 0 after the patch it means the patch caused an2228 // async dep component to unmount and removed its dep. It will cause the2229 // suspense to resolve and we don't need to do anything here.2230 }2231 else {2232 // just normal patch inner content as a fragment2233 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);2234 n2.el = content.el;2235 }2236 suspense.subTree = content;2237 suspense.fallbackTree = fallback;2238 }2239 function resolveSuspense(suspense) {2240 {2241 if (suspense.isResolved) {2242 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);2243 }2244 if (suspense.isUnmounted) {2245 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);2246 }2247 }2248 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;2249 // this is initial anchor on mount2250 let { anchor } = suspense;2251 // unmount fallback tree2252 if (fallbackTree.el) {2253 // if the fallback tree was mounted, it may have been moved2254 // as part of a parent suspense. get the latest anchor for insertion2255 anchor = getNextHostNode(fallbackTree);2256 unmount(fallbackTree, parentComponent, suspense, true);2257 }2258 // move content from off-dom container to actual container2259 move(subTree, container, anchor);2260 const el = (vnode.el = subTree.el);2261 // suspense as the root node of a component...2262 if (parentComponent && parentComponent.subTree === vnode) {2263 parentComponent.vnode.el = el;2264 updateHOCHostEl(parentComponent, el);2265 }2266 // check if there is a pending parent suspense2267 let parent = suspense.parent;2268 let hasUnresolvedAncestor = false;2269 while (parent) {2270 if (!parent.isResolved) {2271 // found a pending parent suspense, merge buffered post jobs2272 // into that parent2273 parent.effects.push(...effects);2274 hasUnresolvedAncestor = true;2275 break;2276 }2277 parent = parent.parent;2278 }2279 // no pending parent suspense, flush all jobs2280 if (!hasUnresolvedAncestor) {2281 queuePostFlushCb(effects);2282 }2283 suspense.isResolved = true;2284 // invoke @resolve event2285 const onResolve = vnode.props && vnode.props.onResolve;2286 if (isFunction(onResolve)) {2287 onResolve();2288 }2289 }2290 function restartSuspense(suspense) {2291 suspense.isResolved = false;2292 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;2293 // move content tree back to the off-dom container2294 const anchor = getNextHostNode(subTree);2295 move(subTree, hiddenContainer, null);2296 // remount the fallback tree2297 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context2298 isSVG, optimized);2299 const el = (vnode.el = fallbackTree.el);2300 // suspense as the root node of a component...2301 if (parentComponent && parentComponent.subTree === vnode) {2302 parentComponent.vnode.el = el;2303 updateHOCHostEl(parentComponent, el);2304 }2305 // invoke @suspense event2306 const onSuspense = vnode.props && vnode.props.onSuspense;2307 if (isFunction(onSuspense)) {2308 onSuspense();2309 }2310 }2311 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2312 if (n1 == null) {2313 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);2314 }2315 else {2316 const instance = (n2.component = n1.component);2317 if (shouldUpdateComponent(n1, n2, optimized)) {2318 if (2319 instance.asyncDep &&2320 !instance.asyncResolved) {2321 // async & still pending - just update props and slots2322 // since the component's reactive effect for render isn't set-up yet2323 {2324 pushWarningContext(n2);2325 }2326 updateComponentPreRender(instance, n2);2327 {2328 popWarningContext();2329 }2330 return;2331 }2332 else {2333 // normal update2334 instance.next = n2;2335 // instance.update is the reactive effect runner.2336 instance.update();2337 }2338 }2339 else {2340 // no update needed. just copy over properties2341 n2.component = n1.component;2342 n2.el = n1.el;2343 }2344 }2345 if (n2.ref !== null && parentComponent !== null) {2346 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);2347 }2348 }2349 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {2350 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));2351 {2352 pushWarningContext(initialVNode);2353 }2354 // resolve props and slots for setup context2355 const propsOptions = initialVNode.type.props;2356 resolveProps(instance, initialVNode.props, propsOptions);2357 resolveSlots(instance, initialVNode.children);2358 // setup stateful logic2359 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {2360 setupStatefulComponent(instance, parentSuspense);2361 }2362 // setup() is async. This component relies on async logic to be resolved2363 // before proceeding2364 if ( instance.asyncDep) {2365 if (!parentSuspense) {2366 // TODO handle this properly2367 throw new Error('Async component without a suspense boundary!');2368 }2369 // parent suspense already resolved, need to re-suspense2370 // use queueJob so it's handled synchronously after patching the current2371 // suspense tree2372 if (parentSuspense.isResolved) {2373 queueJob(() => {2374 restartSuspense(parentSuspense);2375 });2376 }2377 parentSuspense.deps++;2378 instance.asyncDep2379 .catch(err => {2380 handleError(err, instance, 0 /* SETUP_FUNCTION */);2381 })2382 .then(asyncSetupResult => {2383 // component may be unmounted before resolve2384 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {2385 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);2386 }2387 });2388 // give it a placeholder2389 const placeholder = (instance.subTree = createVNode(Comment));2390 processCommentNode(null, placeholder, container, anchor);2391 initialVNode.el = placeholder.el;2392 return;2393 }2394 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);2395 {2396 popWarningContext();2397 }2398 }2399 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {2400 parentSuspense.deps--;2401 // retry from this component2402 instance.asyncResolved = true;2403 const { vnode } = instance;2404 {2405 pushWarningContext(vnode);2406 }2407 handleSetupResult(instance, asyncSetupResult, parentSuspense);2408 setupRenderEffect(instance, parentSuspense, vnode, 2409 // component may have been moved before resolve2410 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);2411 updateHOCHostEl(instance, vnode.el);2412 {2413 popWarningContext();2414 }2415 if (parentSuspense.deps === 0) {2416 resolveSuspense(parentSuspense);2417 }2418 }2419 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {2420 // create reactive effect for rendering2421 let mounted = false;2422 instance.update = effect(function componentEffect() {2423 if (!mounted) {2424 const subTree = (instance.subTree = renderComponentRoot(instance));2425 // beforeMount hook2426 if (instance.bm !== null) {2427 invokeHooks(instance.bm);2428 }2429 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);2430 initialVNode.el = subTree.el;2431 // mounted hook2432 if (instance.m !== null) {2433 queuePostRenderEffect(instance.m, parentSuspense);2434 }2435 mounted = true;2436 }2437 else {2438 // updateComponent2439 // This is triggered by mutation of component's own state (next: null)2440 // OR parent calling processComponent (next: HostVNode)2441 const { next } = instance;2442 {2443 pushWarningContext(next || instance.vnode);2444 }2445 if (next !== null) {2446 updateComponentPreRender(instance, next);2447 }2448 const prevTree = instance.subTree;2449 const nextTree = (instance.subTree = renderComponentRoot(instance));2450 // beforeUpdate hook2451 if (instance.bu !== null) {2452 invokeHooks(instance.bu);2453 }2454 // reset refs2455 // only needed if previous patch had refs2456 if (instance.refs !== EMPTY_OBJ) {2457 instance.refs = {};2458 }2459 patch(prevTree, nextTree, 2460 // parent may have changed if it's in a portal2461 hostParentNode(prevTree.el), 2462 // anchor may have changed if it's in a fragment2463 getNextHostNode(prevTree), instance, parentSuspense, isSVG);2464 instance.vnode.el = nextTree.el;2465 if (next === null) {2466 // self-triggered update. In case of HOC, update parent component2467 // vnode el. HOC is indicated by parent instance's subTree pointing2468 // to child component's vnode2469 updateHOCHostEl(instance, nextTree.el);2470 }2471 // updated hook2472 if (instance.u !== null) {2473 queuePostRenderEffect(instance.u, parentSuspense);2474 }2475 {2476 popWarningContext();2477 }2478 }2479 }, createDevEffectOptions(instance) );2480 }2481 function updateComponentPreRender(instance, nextVNode) {2482 nextVNode.component = instance;2483 instance.vnode = nextVNode;2484 instance.next = null;2485 resolveProps(instance, nextVNode.props, nextVNode.type.props);2486 resolveSlots(instance, nextVNode.children);2487 }2488 function updateHOCHostEl({ vnode, parent }, el) {2489 while (parent && parent.subTree === vnode) {2490 (vnode = parent.vnode).el = el;2491 parent = parent.parent;2492 }2493 }
...
runtime-dom.global.js
Source:runtime-dom.global.js
...1860 fallback: normalizeVNode(null)1861 };1862 }1863 }1864 function createDevEffectOptions(instance) {1865 return {1866 scheduler: queueJob,1867 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1868 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01869 };1870 }1871 function isSameType$1(n1, n2) {1872 return n1.type === n2.type && n1.key === n2.key;1873 }1874 function invokeHooks(hooks, arg) {1875 for (let i = 0; i < hooks.length; i++) {1876 hooks[i](arg);1877 }1878 }1879 function queuePostRenderEffect(fn, suspense) {1880 if (suspense !== null && !suspense.isResolved) {1881 if (isArray(fn)) {1882 suspense.effects.push(...fn);1883 }1884 else {1885 suspense.effects.push(fn);1886 }1887 }1888 else {1889 queuePostFlushCb(fn);1890 }1891 }1892 /**1893 * The createRenderer function accepts two generic arguments:1894 * HostNode and HostElement, corresponding to Node and Element types in the1895 * host environment. For example, for runtime-dom, HostNode would be the DOM1896 * `Node` interface and HostElement would be the DOM `Element` interface.1897 *1898 * Custom renderers can pass in the platform specific types like this:1899 *1900 * ``` js1901 * const { render, createApp } = createRenderer<Node, Element>({1902 * patchProp,1903 * ...nodeOps1904 * })1905 * ```1906 */1907 function createRenderer(options) {1908 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1909 function patch(n1, // null means this is a mount1910 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1911 // patching & not same type, unmount old tree1912 if (n1 != null && !isSameType$1(n1, n2)) {1913 anchor = getNextHostNode(n1);1914 unmount(n1, parentComponent, parentSuspense, true);1915 n1 = null;1916 }1917 const { type, shapeFlag } = n2;1918 switch (type) {1919 case Text:1920 processText(n1, n2, container, anchor);1921 break;1922 case Comment:1923 processCommentNode(n1, n2, container, anchor);1924 break;1925 case Fragment:1926 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1927 break;1928 case Portal:1929 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1930 break;1931 case Suspense:1932 {1933 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1934 }1935 break;1936 default:1937 if (shapeFlag & 1 /* ELEMENT */) {1938 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1939 }1940 else if (shapeFlag & 6 /* COMPONENT */) {1941 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1942 }1943 else {1944 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1945 }1946 }1947 }1948 function processText(n1, n2, container, anchor) {1949 if (n1 == null) {1950 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1951 }1952 else {1953 const el = (n2.el = n1.el);1954 if (n2.children !== n1.children) {1955 hostSetText(el, n2.children);1956 }1957 }1958 }1959 function processCommentNode(n1, n2, container, anchor) {1960 if (n1 == null) {1961 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1962 }1963 else {1964 // there's no support for dynamic comments1965 n2.el = n1.el;1966 }1967 }1968 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1969 if (n1 == null) {1970 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG);1971 }1972 else {1973 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1974 }1975 if (n2.ref !== null && parentComponent !== null) {1976 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1977 }1978 }1979 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG) {1980 const tag = vnode.type;1981 isSVG = isSVG || tag === 'svg';1982 const el = (vnode.el = hostCreateElement(tag, isSVG));1983 const { props, shapeFlag } = vnode;1984 if (props != null) {1985 for (const key in props) {1986 if (isReservedProp(key))1987 continue;1988 hostPatchProp(el, key, props[key], null, isSVG);1989 }1990 if (props.vnodeBeforeMount != null) {1991 invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode);1992 }1993 }1994 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1995 hostSetElementText(el, vnode.children);1996 }1997 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1998 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG);1999 }2000 hostInsert(el, container, anchor);2001 if (props != null && props.vnodeMounted != null) {2002 queuePostRenderEffect(() => {2003 invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode);2004 }, parentSuspense);2005 }2006 }2007 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, start = 0) {2008 for (let i = start; i < children.length; i++) {2009 const child = (children[i] = normalizeVNode(children[i]));2010 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG);2011 }2012 }2013 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {2014 const el = (n2.el = n1.el);2015 const { patchFlag, dynamicChildren } = n2;2016 const oldProps = (n1 && n1.props) || EMPTY_OBJ;2017 const newProps = n2.props || EMPTY_OBJ;2018 if (newProps.vnodeBeforeUpdate != null) {2019 invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1);2020 }2021 if (patchFlag > 0) {2022 // the presence of a patchFlag means this element's render code was2023 // generated by the compiler and can take the fast path.2024 // in this path old node and new node are guaranteed to have the same shape2025 // (i.e. at the exact same position in the source template)2026 if (patchFlag & 16 /* FULL_PROPS */) {2027 // element props contain dynamic keys, full diff needed2028 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2029 }2030 else {2031 // class2032 // this flag is matched when the element has dynamic class bindings.2033 if (patchFlag & 2 /* CLASS */) {2034 if (oldProps.class !== newProps.class) {2035 hostPatchProp(el, 'class', newProps.class, null, isSVG);2036 }2037 }2038 // style2039 // this flag is matched when the element has dynamic style bindings2040 if (patchFlag & 4 /* STYLE */) {2041 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);2042 }2043 // props2044 // This flag is matched when the element has dynamic prop/attr bindings2045 // other than class and style. The keys of dynamic prop/attrs are saved for2046 // faster iteration.2047 // Note dynamic keys like :[foo]="bar" will cause this optimization to2048 // bail out and go through a full diff because we need to unset the old key2049 if (patchFlag & 8 /* PROPS */) {2050 // if the flag is present then dynamicProps must be non-null2051 const propsToUpdate = n2.dynamicProps;2052 for (let i = 0; i < propsToUpdate.length; i++) {2053 const key = propsToUpdate[i];2054 const prev = oldProps[key];2055 const next = newProps[key];2056 if (prev !== next) {2057 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);2058 }2059 }2060 }2061 }2062 // text2063 // This flag is matched when the element has only dynamic text children.2064 // this flag is terminal (i.e. skips children diffing).2065 if (patchFlag & 1 /* TEXT */) {2066 if (n1.children !== n2.children) {2067 hostSetElementText(el, n2.children);2068 }2069 return; // terminal2070 }2071 }2072 else if (!optimized) {2073 // unoptimized, full diff2074 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2075 }2076 if (dynamicChildren != null) {2077 // children fast path2078 const oldDynamicChildren = n1.dynamicChildren;2079 for (let i = 0; i < dynamicChildren.length; i++) {2080 patch(oldDynamicChildren[i], dynamicChildren[i], el, null, parentComponent, parentSuspense, isSVG, true);2081 }2082 }2083 else if (!optimized) {2084 // full diff2085 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);2086 }2087 if (newProps.vnodeUpdated != null) {2088 queuePostRenderEffect(() => {2089 invokeDirectiveHook(newProps.vnodeUpdated, parentComponent, n2, n1);2090 }, parentSuspense);2091 }2092 }2093 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {2094 if (oldProps !== newProps) {2095 for (const key in newProps) {2096 if (isReservedProp(key))2097 continue;2098 const next = newProps[key];2099 const prev = oldProps[key];2100 if (next !== prev) {2101 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2102 }2103 }2104 if (oldProps !== EMPTY_OBJ) {2105 for (const key in oldProps) {2106 if (isReservedProp(key))2107 continue;2108 if (!(key in newProps)) {2109 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2110 }2111 }2112 }2113 }2114 }2115 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2116 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));2117 const fragmentEndAnchor = (n2.anchor = n12118 ? n1.anchor2119 : hostCreateComment(''));2120 if (n1 == null) {2121 hostInsert(fragmentStartAnchor, container, anchor);2122 hostInsert(fragmentEndAnchor, container, anchor);2123 // a fragment can only have array children2124 // since they are either generated by the compiler, or implicitly created2125 // from arrays.2126 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG);2127 }2128 else {2129 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);2130 }2131 }2132 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2133 const targetSelector = n2.props && n2.props.target;2134 const { patchFlag, shapeFlag, children } = n2;2135 if (n1 == null) {2136 const target = (n2.target = isString(targetSelector)2137 ? hostQuerySelector(targetSelector)2138 : null);2139 if (target != null) {2140 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2141 hostSetElementText(target, children);2142 }2143 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2144 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG);2145 }2146 }2147 else {2148 warn('Invalid Portal target on mount:', target, `(${typeof target})`);2149 }2150 }2151 else {2152 // update content2153 const target = (n2.target = n1.target);2154 if (patchFlag === 1 /* TEXT */) {2155 hostSetElementText(target, children);2156 }2157 else if (!optimized) {2158 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);2159 }2160 // target changed2161 if (targetSelector !== (n1.props && n1.props.target)) {2162 const nextTarget = (n2.target = isString(targetSelector)2163 ? hostQuerySelector(targetSelector)2164 : null);2165 if (nextTarget != null) {2166 // move content2167 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2168 hostSetElementText(target, '');2169 hostSetElementText(nextTarget, children);2170 }2171 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2172 for (let i = 0; i < children.length; i++) {2173 move(children[i], nextTarget, null);2174 }2175 }2176 }2177 else {2178 warn('Invalid Portal target on update:', target, `(${typeof target})`);2179 }2180 }2181 }2182 // insert an empty node as the placeholder for the portal2183 processCommentNode(n1, n2, container, anchor);2184 }2185 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2186 if (n1 == null) {2187 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2188 }2189 else {2190 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);2191 }2192 }2193 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2194 const hiddenContainer = hostCreateElement('div');2195 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));2196 const { content, fallback } = normalizeSuspenseChildren(n2);2197 suspense.subTree = content;2198 suspense.fallbackTree = fallback;2199 // start mounting the content subtree in an off-dom container2200 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);2201 // now check if we have encountered any async deps2202 if (suspense.deps > 0) {2203 // mount the fallback tree2204 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context2205 isSVG, optimized);2206 n2.el = fallback.el;2207 }2208 else {2209 // Suspense has no async deps. Just resolve.2210 resolveSuspense(suspense);2211 }2212 }2213 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {2214 const suspense = (n2.suspense = n1.suspense);2215 suspense.vnode = n2;2216 const { content, fallback } = normalizeSuspenseChildren(n2);2217 const oldSubTree = suspense.subTree;2218 const oldFallbackTree = suspense.fallbackTree;2219 if (!suspense.isResolved) {2220 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);2221 if (suspense.deps > 0) {2222 // still pending. patch the fallback tree.2223 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context2224 isSVG, optimized);2225 n2.el = fallback.el;2226 }2227 // If deps somehow becomes 0 after the patch it means the patch caused an2228 // async dep component to unmount and removed its dep. It will cause the2229 // suspense to resolve and we don't need to do anything here.2230 }2231 else {2232 // just normal patch inner content as a fragment2233 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);2234 n2.el = content.el;2235 }2236 suspense.subTree = content;2237 suspense.fallbackTree = fallback;2238 }2239 function resolveSuspense(suspense) {2240 {2241 if (suspense.isResolved) {2242 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);2243 }2244 if (suspense.isUnmounted) {2245 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);2246 }2247 }2248 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;2249 // this is initial anchor on mount2250 let { anchor } = suspense;2251 // unmount fallback tree2252 if (fallbackTree.el) {2253 // if the fallback tree was mounted, it may have been moved2254 // as part of a parent suspense. get the latest anchor for insertion2255 anchor = getNextHostNode(fallbackTree);2256 unmount(fallbackTree, parentComponent, suspense, true);2257 }2258 // move content from off-dom container to actual container2259 move(subTree, container, anchor);2260 const el = (vnode.el = subTree.el);2261 // suspense as the root node of a component...2262 if (parentComponent && parentComponent.subTree === vnode) {2263 parentComponent.vnode.el = el;2264 updateHOCHostEl(parentComponent, el);2265 }2266 // check if there is a pending parent suspense2267 let parent = suspense.parent;2268 let hasUnresolvedAncestor = false;2269 while (parent) {2270 if (!parent.isResolved) {2271 // found a pending parent suspense, merge buffered post jobs2272 // into that parent2273 parent.effects.push(...effects);2274 hasUnresolvedAncestor = true;2275 break;2276 }2277 parent = parent.parent;2278 }2279 // no pending parent suspense, flush all jobs2280 if (!hasUnresolvedAncestor) {2281 queuePostFlushCb(effects);2282 }2283 suspense.isResolved = true;2284 // invoke @resolve event2285 const onResolve = vnode.props && vnode.props.onResolve;2286 if (isFunction(onResolve)) {2287 onResolve();2288 }2289 }2290 function restartSuspense(suspense) {2291 suspense.isResolved = false;2292 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;2293 // move content tree back to the off-dom container2294 const anchor = getNextHostNode(subTree);2295 move(subTree, hiddenContainer, null);2296 // remount the fallback tree2297 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context2298 isSVG, optimized);2299 const el = (vnode.el = fallbackTree.el);2300 // suspense as the root node of a component...2301 if (parentComponent && parentComponent.subTree === vnode) {2302 parentComponent.vnode.el = el;2303 updateHOCHostEl(parentComponent, el);2304 }2305 // invoke @suspense event2306 const onSuspense = vnode.props && vnode.props.onSuspense;2307 if (isFunction(onSuspense)) {2308 onSuspense();2309 }2310 }2311 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2312 if (n1 == null) {2313 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);2314 }2315 else {2316 const instance = (n2.component = n1.component);2317 if (shouldUpdateComponent(n1, n2, optimized)) {2318 if (2319 instance.asyncDep &&2320 !instance.asyncResolved) {2321 // async & still pending - just update props and slots2322 // since the component's reactive effect for render isn't set-up yet2323 {2324 pushWarningContext(n2);2325 }2326 updateComponentPreRender(instance, n2);2327 {2328 popWarningContext();2329 }2330 return;2331 }2332 else {2333 // normal update2334 instance.next = n2;2335 // instance.update is the reactive effect runner.2336 instance.update();2337 }2338 }2339 else {2340 // no update needed. just copy over properties2341 n2.component = n1.component;2342 n2.el = n1.el;2343 }2344 }2345 if (n2.ref !== null && parentComponent !== null) {2346 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);2347 }2348 }2349 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {2350 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));2351 {2352 pushWarningContext(initialVNode);2353 }2354 // resolve props and slots for setup context2355 const propsOptions = initialVNode.type.props;2356 resolveProps(instance, initialVNode.props, propsOptions);2357 resolveSlots(instance, initialVNode.children);2358 // setup stateful logic2359 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {2360 setupStatefulComponent(instance, parentSuspense);2361 }2362 // setup() is async. This component relies on async logic to be resolved2363 // before proceeding2364 if ( instance.asyncDep) {2365 if (!parentSuspense) {2366 // TODO handle this properly2367 throw new Error('Async component without a suspense boundary!');2368 }2369 // parent suspense already resolved, need to re-suspense2370 // use queueJob so it's handled synchronously after patching the current2371 // suspense tree2372 if (parentSuspense.isResolved) {2373 queueJob(() => {2374 restartSuspense(parentSuspense);2375 });2376 }2377 parentSuspense.deps++;2378 instance.asyncDep2379 .catch(err => {2380 handleError(err, instance, 0 /* SETUP_FUNCTION */);2381 })2382 .then(asyncSetupResult => {2383 // component may be unmounted before resolve2384 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {2385 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);2386 }2387 });2388 // give it a placeholder2389 const placeholder = (instance.subTree = createVNode(Comment));2390 processCommentNode(null, placeholder, container, anchor);2391 initialVNode.el = placeholder.el;2392 return;2393 }2394 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);2395 {2396 popWarningContext();2397 }2398 }2399 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {2400 parentSuspense.deps--;2401 // retry from this component2402 instance.asyncResolved = true;2403 const { vnode } = instance;2404 {2405 pushWarningContext(vnode);2406 }2407 handleSetupResult(instance, asyncSetupResult, parentSuspense);2408 setupRenderEffect(instance, parentSuspense, vnode, 2409 // component may have been moved before resolve2410 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);2411 updateHOCHostEl(instance, vnode.el);2412 {2413 popWarningContext();2414 }2415 if (parentSuspense.deps === 0) {2416 resolveSuspense(parentSuspense);2417 }2418 }2419 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {2420 // create reactive effect for rendering2421 let mounted = false;2422 instance.update = effect(function componentEffect() {2423 if (!mounted) {2424 const subTree = (instance.subTree = renderComponentRoot(instance));2425 // beforeMount hook2426 if (instance.bm !== null) {2427 invokeHooks(instance.bm);2428 }2429 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);2430 initialVNode.el = subTree.el;2431 // mounted hook2432 if (instance.m !== null) {2433 queuePostRenderEffect(instance.m, parentSuspense);2434 }2435 mounted = true;2436 }2437 else {2438 // updateComponent2439 // This is triggered by mutation of component's own state (next: null)2440 // OR parent calling processComponent (next: HostVNode)2441 const { next } = instance;2442 {2443 pushWarningContext(next || instance.vnode);2444 }2445 if (next !== null) {2446 updateComponentPreRender(instance, next);2447 }2448 const prevTree = instance.subTree;2449 const nextTree = (instance.subTree = renderComponentRoot(instance));2450 // beforeUpdate hook2451 if (instance.bu !== null) {2452 invokeHooks(instance.bu);2453 }2454 // reset refs2455 // only needed if previous patch had refs2456 if (instance.refs !== EMPTY_OBJ) {2457 instance.refs = {};2458 }2459 patch(prevTree, nextTree, 2460 // parent may have changed if it's in a portal2461 hostParentNode(prevTree.el), 2462 // anchor may have changed if it's in a fragment2463 getNextHostNode(prevTree), instance, parentSuspense, isSVG);2464 instance.vnode.el = nextTree.el;2465 if (next === null) {2466 // self-triggered update. In case of HOC, update parent component2467 // vnode el. HOC is indicated by parent instance's subTree pointing2468 // to child component's vnode2469 updateHOCHostEl(instance, nextTree.el);2470 }2471 // updated hook2472 if (instance.u !== null) {2473 queuePostRenderEffect(instance.u, parentSuspense);2474 }2475 {2476 popWarningContext();2477 }2478 }2479 }, createDevEffectOptions(instance) );2480 }2481 function updateComponentPreRender(instance, nextVNode) {2482 nextVNode.component = instance;2483 instance.vnode = nextVNode;2484 instance.next = null;2485 resolveProps(instance, nextVNode.props, nextVNode.type.props);2486 resolveSlots(instance, nextVNode.children);2487 }2488 function updateHOCHostEl({ vnode, parent }, el) {2489 while (parent && parent.subTree === vnode) {2490 (vnode = parent.vnode).el = el;2491 parent = parent.parent;2492 }2493 }
...
runtime-dom.esm-browser.js
Source:runtime-dom.esm-browser.js
...1848 };1849 }1850}18511852function createDevEffectOptions(instance) {1853 return {1854 scheduler: queueJob,1855 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1856 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01857 };1858}1859function isSameType$1(n1, n2) {1860 return n1.type === n2.type && n1.key === n2.key;1861}1862function invokeHooks(hooks, arg) {1863 for (let i = 0; i < hooks.length; i++) {1864 hooks[i](arg);1865 }1866}1867function queuePostRenderEffect(fn, suspense) {1868 if (suspense !== null && !suspense.isResolved) {1869 if (isArray(fn)) {1870 suspense.effects.push(...fn);1871 }1872 else {1873 suspense.effects.push(fn);1874 }1875 }1876 else {1877 queuePostFlushCb(fn);1878 }1879}1880/**1881 * The createRenderer function accepts two generic arguments:1882 * HostNode and HostElement, corresponding to Node and Element types in the1883 * host environment. For example, for runtime-dom, HostNode would be the DOM1884 * `Node` interface and HostElement would be the DOM `Element` interface.1885 *1886 * Custom renderers can pass in the platform specific types like this:1887 *1888 * ``` js1889 * const { render, createApp } = createRenderer<Node, Element>({1890 * patchProp,1891 * ...nodeOps1892 * })1893 * ```1894 */1895function createRenderer(options) {1896 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1897 function patch(n1, // null means this is a mount1898 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1899 // patching & not same type, unmount old tree1900 if (n1 != null && !isSameType$1(n1, n2)) {1901 anchor = getNextHostNode(n1);1902 unmount(n1, parentComponent, parentSuspense, true);1903 n1 = null;1904 }1905 const { type, shapeFlag } = n2;1906 switch (type) {1907 case Text:1908 processText(n1, n2, container, anchor);1909 break;1910 case Comment:1911 processCommentNode(n1, n2, container, anchor);1912 break;1913 case Fragment:1914 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1915 break;1916 case Portal:1917 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1918 break;1919 case Suspense:1920 {1921 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1922 }1923 break;1924 default:1925 if (shapeFlag & 1 /* ELEMENT */) {1926 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1927 }1928 else if (shapeFlag & 6 /* COMPONENT */) {1929 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1930 }1931 else {1932 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1933 }1934 }1935 }1936 function processText(n1, n2, container, anchor) {1937 if (n1 == null) {1938 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1939 }1940 else {1941 const el = (n2.el = n1.el);1942 if (n2.children !== n1.children) {1943 hostSetText(el, n2.children);1944 }1945 }1946 }1947 function processCommentNode(n1, n2, container, anchor) {1948 if (n1 == null) {1949 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1950 }1951 else {1952 // there's no support for dynamic comments1953 n2.el = n1.el;1954 }1955 }1956 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1957 if (n1 == null) {1958 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG);1959 }1960 else {1961 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1962 }1963 if (n2.ref !== null && parentComponent !== null) {1964 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1965 }1966 }1967 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG) {1968 const tag = vnode.type;1969 isSVG = isSVG || tag === 'svg';1970 const el = (vnode.el = hostCreateElement(tag, isSVG));1971 const { props, shapeFlag } = vnode;1972 if (props != null) {1973 for (const key in props) {1974 if (isReservedProp(key))1975 continue;1976 hostPatchProp(el, key, props[key], null, isSVG);1977 }1978 if (props.vnodeBeforeMount != null) {1979 invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode);1980 }1981 }1982 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1983 hostSetElementText(el, vnode.children);1984 }1985 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1986 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG);1987 }1988 hostInsert(el, container, anchor);1989 if (props != null && props.vnodeMounted != null) {1990 queuePostRenderEffect(() => {1991 invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode);1992 }, parentSuspense);1993 }1994 }1995 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, start = 0) {1996 for (let i = start; i < children.length; i++) {1997 const child = (children[i] = normalizeVNode(children[i]));1998 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG);1999 }2000 }2001 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {2002 const el = (n2.el = n1.el);2003 const { patchFlag, dynamicChildren } = n2;2004 const oldProps = (n1 && n1.props) || EMPTY_OBJ;2005 const newProps = n2.props || EMPTY_OBJ;2006 if (newProps.vnodeBeforeUpdate != null) {2007 invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1);2008 }2009 if (patchFlag > 0) {2010 // the presence of a patchFlag means this element's render code was2011 // generated by the compiler and can take the fast path.2012 // in this path old node and new node are guaranteed to have the same shape2013 // (i.e. at the exact same position in the source template)2014 if (patchFlag & 16 /* FULL_PROPS */) {2015 // element props contain dynamic keys, full diff needed2016 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2017 }2018 else {2019 // class2020 // this flag is matched when the element has dynamic class bindings.2021 if (patchFlag & 2 /* CLASS */) {2022 if (oldProps.class !== newProps.class) {2023 hostPatchProp(el, 'class', newProps.class, null, isSVG);2024 }2025 }2026 // style2027 // this flag is matched when the element has dynamic style bindings2028 if (patchFlag & 4 /* STYLE */) {2029 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);2030 }2031 // props2032 // This flag is matched when the element has dynamic prop/attr bindings2033 // other than class and style. The keys of dynamic prop/attrs are saved for2034 // faster iteration.2035 // Note dynamic keys like :[foo]="bar" will cause this optimization to2036 // bail out and go through a full diff because we need to unset the old key2037 if (patchFlag & 8 /* PROPS */) {2038 // if the flag is present then dynamicProps must be non-null2039 const propsToUpdate = n2.dynamicProps;2040 for (let i = 0; i < propsToUpdate.length; i++) {2041 const key = propsToUpdate[i];2042 const prev = oldProps[key];2043 const next = newProps[key];2044 if (prev !== next) {2045 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);2046 }2047 }2048 }2049 }2050 // text2051 // This flag is matched when the element has only dynamic text children.2052 // this flag is terminal (i.e. skips children diffing).2053 if (patchFlag & 1 /* TEXT */) {2054 if (n1.children !== n2.children) {2055 hostSetElementText(el, n2.children);2056 }2057 return; // terminal2058 }2059 }2060 else if (!optimized) {2061 // unoptimized, full diff2062 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);2063 }2064 if (dynamicChildren != null) {2065 // children fast path2066 const oldDynamicChildren = n1.dynamicChildren;2067 for (let i = 0; i < dynamicChildren.length; i++) {2068 patch(oldDynamicChildren[i], dynamicChildren[i], el, null, parentComponent, parentSuspense, isSVG, true);2069 }2070 }2071 else if (!optimized) {2072 // full diff2073 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);2074 }2075 if (newProps.vnodeUpdated != null) {2076 queuePostRenderEffect(() => {2077 invokeDirectiveHook(newProps.vnodeUpdated, parentComponent, n2, n1);2078 }, parentSuspense);2079 }2080 }2081 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {2082 if (oldProps !== newProps) {2083 for (const key in newProps) {2084 if (isReservedProp(key))2085 continue;2086 const next = newProps[key];2087 const prev = oldProps[key];2088 if (next !== prev) {2089 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2090 }2091 }2092 if (oldProps !== EMPTY_OBJ) {2093 for (const key in oldProps) {2094 if (isReservedProp(key))2095 continue;2096 if (!(key in newProps)) {2097 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);2098 }2099 }2100 }2101 }2102 }2103 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2104 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));2105 const fragmentEndAnchor = (n2.anchor = n12106 ? n1.anchor2107 : hostCreateComment(''));2108 if (n1 == null) {2109 hostInsert(fragmentStartAnchor, container, anchor);2110 hostInsert(fragmentEndAnchor, container, anchor);2111 // a fragment can only have array children2112 // since they are either generated by the compiler, or implicitly created2113 // from arrays.2114 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG);2115 }2116 else {2117 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);2118 }2119 }2120 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2121 const targetSelector = n2.props && n2.props.target;2122 const { patchFlag, shapeFlag, children } = n2;2123 if (n1 == null) {2124 const target = (n2.target = isString(targetSelector)2125 ? hostQuerySelector(targetSelector)2126 : null);2127 if (target != null) {2128 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2129 hostSetElementText(target, children);2130 }2131 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2132 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG);2133 }2134 }2135 else {2136 warn('Invalid Portal target on mount:', target, `(${typeof target})`);2137 }2138 }2139 else {2140 // update content2141 const target = (n2.target = n1.target);2142 if (patchFlag === 1 /* TEXT */) {2143 hostSetElementText(target, children);2144 }2145 else if (!optimized) {2146 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);2147 }2148 // target changed2149 if (targetSelector !== (n1.props && n1.props.target)) {2150 const nextTarget = (n2.target = isString(targetSelector)2151 ? hostQuerySelector(targetSelector)2152 : null);2153 if (nextTarget != null) {2154 // move content2155 if (shapeFlag & 8 /* TEXT_CHILDREN */) {2156 hostSetElementText(target, '');2157 hostSetElementText(nextTarget, children);2158 }2159 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {2160 for (let i = 0; i < children.length; i++) {2161 move(children[i], nextTarget, null);2162 }2163 }2164 }2165 else {2166 warn('Invalid Portal target on update:', target, `(${typeof target})`);2167 }2168 }2169 }2170 // insert an empty node as the placeholder for the portal2171 processCommentNode(n1, n2, container, anchor);2172 }2173 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2174 if (n1 == null) {2175 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);2176 }2177 else {2178 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);2179 }2180 }2181 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2182 const hiddenContainer = hostCreateElement('div');2183 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));2184 const { content, fallback } = normalizeSuspenseChildren(n2);2185 suspense.subTree = content;2186 suspense.fallbackTree = fallback;2187 // start mounting the content subtree in an off-dom container2188 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);2189 // now check if we have encountered any async deps2190 if (suspense.deps > 0) {2191 // mount the fallback tree2192 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context2193 isSVG, optimized);2194 n2.el = fallback.el;2195 }2196 else {2197 // Suspense has no async deps. Just resolve.2198 resolveSuspense(suspense);2199 }2200 }2201 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {2202 const suspense = (n2.suspense = n1.suspense);2203 suspense.vnode = n2;2204 const { content, fallback } = normalizeSuspenseChildren(n2);2205 const oldSubTree = suspense.subTree;2206 const oldFallbackTree = suspense.fallbackTree;2207 if (!suspense.isResolved) {2208 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);2209 if (suspense.deps > 0) {2210 // still pending. patch the fallback tree.2211 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context2212 isSVG, optimized);2213 n2.el = fallback.el;2214 }2215 // If deps somehow becomes 0 after the patch it means the patch caused an2216 // async dep component to unmount and removed its dep. It will cause the2217 // suspense to resolve and we don't need to do anything here.2218 }2219 else {2220 // just normal patch inner content as a fragment2221 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);2222 n2.el = content.el;2223 }2224 suspense.subTree = content;2225 suspense.fallbackTree = fallback;2226 }2227 function resolveSuspense(suspense) {2228 {2229 if (suspense.isResolved) {2230 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);2231 }2232 if (suspense.isUnmounted) {2233 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);2234 }2235 }2236 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;2237 // this is initial anchor on mount2238 let { anchor } = suspense;2239 // unmount fallback tree2240 if (fallbackTree.el) {2241 // if the fallback tree was mounted, it may have been moved2242 // as part of a parent suspense. get the latest anchor for insertion2243 anchor = getNextHostNode(fallbackTree);2244 unmount(fallbackTree, parentComponent, suspense, true);2245 }2246 // move content from off-dom container to actual container2247 move(subTree, container, anchor);2248 const el = (vnode.el = subTree.el);2249 // suspense as the root node of a component...2250 if (parentComponent && parentComponent.subTree === vnode) {2251 parentComponent.vnode.el = el;2252 updateHOCHostEl(parentComponent, el);2253 }2254 // check if there is a pending parent suspense2255 let parent = suspense.parent;2256 let hasUnresolvedAncestor = false;2257 while (parent) {2258 if (!parent.isResolved) {2259 // found a pending parent suspense, merge buffered post jobs2260 // into that parent2261 parent.effects.push(...effects);2262 hasUnresolvedAncestor = true;2263 break;2264 }2265 parent = parent.parent;2266 }2267 // no pending parent suspense, flush all jobs2268 if (!hasUnresolvedAncestor) {2269 queuePostFlushCb(effects);2270 }2271 suspense.isResolved = true;2272 // invoke @resolve event2273 const onResolve = vnode.props && vnode.props.onResolve;2274 if (isFunction(onResolve)) {2275 onResolve();2276 }2277 }2278 function restartSuspense(suspense) {2279 suspense.isResolved = false;2280 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;2281 // move content tree back to the off-dom container2282 const anchor = getNextHostNode(subTree);2283 move(subTree, hiddenContainer, null);2284 // remount the fallback tree2285 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context2286 isSVG, optimized);2287 const el = (vnode.el = fallbackTree.el);2288 // suspense as the root node of a component...2289 if (parentComponent && parentComponent.subTree === vnode) {2290 parentComponent.vnode.el = el;2291 updateHOCHostEl(parentComponent, el);2292 }2293 // invoke @suspense event2294 const onSuspense = vnode.props && vnode.props.onSuspense;2295 if (isFunction(onSuspense)) {2296 onSuspense();2297 }2298 }2299 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {2300 if (n1 == null) {2301 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);2302 }2303 else {2304 const instance = (n2.component = n1.component);2305 if (shouldUpdateComponent(n1, n2, optimized)) {2306 if (2307 instance.asyncDep &&2308 !instance.asyncResolved) {2309 // async & still pending - just update props and slots2310 // since the component's reactive effect for render isn't set-up yet2311 {2312 pushWarningContext(n2);2313 }2314 updateComponentPreRender(instance, n2);2315 {2316 popWarningContext();2317 }2318 return;2319 }2320 else {2321 // normal update2322 instance.next = n2;2323 // instance.update is the reactive effect runner.2324 instance.update();2325 }2326 }2327 else {2328 // no update needed. just copy over properties2329 n2.component = n1.component;2330 n2.el = n1.el;2331 }2332 }2333 if (n2.ref !== null && parentComponent !== null) {2334 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);2335 }2336 }2337 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {2338 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));2339 {2340 pushWarningContext(initialVNode);2341 }2342 // resolve props and slots for setup context2343 const propsOptions = initialVNode.type.props;2344 resolveProps(instance, initialVNode.props, propsOptions);2345 resolveSlots(instance, initialVNode.children);2346 // setup stateful logic2347 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {2348 setupStatefulComponent(instance, parentSuspense);2349 }2350 // setup() is async. This component relies on async logic to be resolved2351 // before proceeding2352 if ( instance.asyncDep) {2353 if (!parentSuspense) {2354 // TODO handle this properly2355 throw new Error('Async component without a suspense boundary!');2356 }2357 // parent suspense already resolved, need to re-suspense2358 // use queueJob so it's handled synchronously after patching the current2359 // suspense tree2360 if (parentSuspense.isResolved) {2361 queueJob(() => {2362 restartSuspense(parentSuspense);2363 });2364 }2365 parentSuspense.deps++;2366 instance.asyncDep2367 .catch(err => {2368 handleError(err, instance, 0 /* SETUP_FUNCTION */);2369 })2370 .then(asyncSetupResult => {2371 // component may be unmounted before resolve2372 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {2373 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);2374 }2375 });2376 // give it a placeholder2377 const placeholder = (instance.subTree = createVNode(Comment));2378 processCommentNode(null, placeholder, container, anchor);2379 initialVNode.el = placeholder.el;2380 return;2381 }2382 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);2383 {2384 popWarningContext();2385 }2386 }2387 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {2388 parentSuspense.deps--;2389 // retry from this component2390 instance.asyncResolved = true;2391 const { vnode } = instance;2392 {2393 pushWarningContext(vnode);2394 }2395 handleSetupResult(instance, asyncSetupResult, parentSuspense);2396 setupRenderEffect(instance, parentSuspense, vnode,2397 // component may have been moved before resolve2398 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);2399 updateHOCHostEl(instance, vnode.el);2400 {2401 popWarningContext();2402 }2403 if (parentSuspense.deps === 0) {2404 resolveSuspense(parentSuspense);2405 }2406 }2407 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {2408 // create reactive effect for rendering2409 let mounted = false;2410 instance.update = effect(function componentEffect() {2411 if (!mounted) {2412 const subTree = (instance.subTree = renderComponentRoot(instance));2413 // beforeMount hook2414 if (instance.bm !== null) {2415 invokeHooks(instance.bm);2416 }2417 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);2418 initialVNode.el = subTree.el;2419 // mounted hook2420 if (instance.m !== null) {2421 queuePostRenderEffect(instance.m, parentSuspense);2422 }2423 mounted = true;2424 }2425 else {2426 // updateComponent2427 // This is triggered by mutation of component's own state (next: null)2428 // OR parent calling processComponent (next: HostVNode)2429 const { next } = instance;2430 {2431 pushWarningContext(next || instance.vnode);2432 }2433 if (next !== null) {2434 updateComponentPreRender(instance, next);2435 }2436 const prevTree = instance.subTree;2437 const nextTree = (instance.subTree = renderComponentRoot(instance));2438 // beforeUpdate hook2439 if (instance.bu !== null) {2440 invokeHooks(instance.bu);2441 }2442 // reset refs2443 // only needed if previous patch had refs2444 if (instance.refs !== EMPTY_OBJ) {2445 instance.refs = {};2446 }2447 patch(prevTree, nextTree,2448 // parent may have changed if it's in a portal2449 hostParentNode(prevTree.el),2450 // anchor may have changed if it's in a fragment2451 getNextHostNode(prevTree), instance, parentSuspense, isSVG);2452 instance.vnode.el = nextTree.el;2453 if (next === null) {2454 // self-triggered update. In case of HOC, update parent component2455 // vnode el. HOC is indicated by parent instance's subTree pointing2456 // to child component's vnode2457 updateHOCHostEl(instance, nextTree.el);2458 }2459 // updated hook2460 if (instance.u !== null) {2461 queuePostRenderEffect(instance.u, parentSuspense);2462 }2463 {2464 popWarningContext();2465 }2466 }2467 }, createDevEffectOptions(instance) );2468 }2469 function updateComponentPreRender(instance, nextVNode) {2470 nextVNode.component = instance;2471 instance.vnode = nextVNode;2472 instance.next = null;2473 resolveProps(instance, nextVNode.props, nextVNode.type.props);2474 resolveSlots(instance, nextVNode.children);2475 }2476 function updateHOCHostEl({ vnode, parent }, el) {2477 while (parent && parent.subTree === vnode) {2478 (vnode = parent.vnode).el = el;2479 parent = parent.parent;2480 }2481 }
...
vue.runtime.esm.js
Source:vue.runtime.esm.js
...3364}3365const prodEffectOptions = {3366 scheduler: queueJob3367};3368function createDevEffectOptions(instance) {3369 return {3370 scheduler: queueJob,3371 onTrack: instance.rtc ? e => invokeArrayFns(instance.rtc, e) : void 0,3372 onTrigger: instance.rtg ? e => invokeArrayFns(instance.rtg, e) : void 03373 };3374}3375function setupRenderEffect(instance) {3376 // create reactive effect for rendering3377 instance.update = effect(function componentEffect() {3378 if (!instance.isMounted) {3379 instance.render && instance.render.call(instance.proxy);3380 patch(instance);3381 }3382 else {3383 instance.render && instance.render.call(instance.proxy);3384 // updateComponent3385 const { bu, u } = instance;3386 // beforeUpdate hook3387 if (bu) {3388 invokeArrayFns(bu);3389 }3390 patch(instance);3391 // updated hook3392 if (u) {3393 queuePostRenderEffect$1(u);3394 }3395 }3396 }, (process.env.NODE_ENV !== 'production') ? createDevEffectOptions(instance) : prodEffectOptions);3397}3398function unmountComponent(instance) {3399 const { bum, effects, update, um } = instance;3400 // beforeUnmount hook3401 if (bum) {3402 invokeArrayFns(bum);3403 }3404 if (effects) {3405 for (let i = 0; i < effects.length; i++) {3406 stop(effects[i]);3407 }3408 }3409 // update may be null if a component is unmounted before its async3410 // setup has resolved.
...
runtime-core.cjs.js
Source:runtime-core.cjs.js
...1223 fallback: normalizeVNode(null)1224 };1225 }1226}1227function createDevEffectOptions(instance) {1228 return {1229 scheduler: queueJob,1230 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1231 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01232 };1233}1234function isSameType$1(n1, n2) {1235 return n1.type === n2.type && n1.key === n2.key;1236}1237function invokeHooks(hooks, arg) {1238 for (let i = 0; i < hooks.length; i++) {1239 hooks[i](arg);1240 }1241}1242function queuePostRenderEffect(fn, suspense) {1243 if (suspense !== null && !suspense.isResolved) {1244 if (isArray(fn)) {1245 suspense.effects.push(...fn);1246 }1247 else {1248 suspense.effects.push(fn);1249 }1250 }1251 else {1252 queuePostFlushCb(fn);1253 }1254}1255/**1256 * The createRenderer function accepts two generic arguments:1257 * HostNode and HostElement, corresponding to Node and Element types in the1258 * host environment. For example, for runtime-dom, HostNode would be the DOM1259 * `Node` interface and HostElement would be the DOM `Element` interface.1260 *1261 * Custom renderers can pass in the platform specific types like this:1262 *1263 * ``` js1264 * const { render, createApp } = createRenderer<Node, Element>({1265 * patchProp,1266 * ...nodeOps1267 * })1268 * ```1269 */1270function createRenderer(options) {1271 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1272 function patch(n1, // null means this is a mount1273 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1274 // patching & not same type, unmount old tree1275 if (n1 != null && !isSameType$1(n1, n2)) {1276 anchor = getNextHostNode(n1);1277 unmount(n1, parentComponent, parentSuspense, true);1278 n1 = null;1279 }1280 const { type, shapeFlag } = n2;1281 switch (type) {1282 case Text:1283 processText(n1, n2, container, anchor);1284 break;1285 case Comment:1286 processCommentNode(n1, n2, container, anchor);1287 break;1288 case Fragment:1289 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1290 break;1291 case Portal:1292 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1293 break;1294 case Suspense:1295 {1296 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1297 }1298 break;1299 default:1300 if (shapeFlag & 1 /* ELEMENT */) {1301 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1302 }1303 else if (shapeFlag & 6 /* COMPONENT */) {1304 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1305 }1306 else {1307 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1308 }1309 }1310 }1311 function processText(n1, n2, container, anchor) {1312 if (n1 == null) {1313 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1314 }1315 else {1316 const el = (n2.el = n1.el);1317 if (n2.children !== n1.children) {1318 hostSetText(el, n2.children);1319 }1320 }1321 }1322 function processCommentNode(n1, n2, container, anchor) {1323 if (n1 == null) {1324 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1325 }1326 else {1327 // there's no support for dynamic comments1328 n2.el = n1.el;1329 }1330 }1331 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1332 if (n1 == null) {1333 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG);1334 }1335 else {1336 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1337 }1338 if (n2.ref !== null && parentComponent !== null) {1339 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1340 }1341 }1342 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG) {1343 const tag = vnode.type;1344 isSVG = isSVG || tag === 'svg';1345 const el = (vnode.el = hostCreateElement(tag, isSVG));1346 const { props, shapeFlag } = vnode;1347 if (props != null) {1348 for (const key in props) {1349 if (isReservedProp(key))1350 continue;1351 hostPatchProp(el, key, props[key], null, isSVG);1352 }1353 if (props.vnodeBeforeMount != null) {1354 invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode);1355 }1356 }1357 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1358 hostSetElementText(el, vnode.children);1359 }1360 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1361 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG);1362 }1363 hostInsert(el, container, anchor);1364 if (props != null && props.vnodeMounted != null) {1365 queuePostRenderEffect(() => {1366 invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode);1367 }, parentSuspense);1368 }1369 }1370 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, start = 0) {1371 for (let i = start; i < children.length; i++) {1372 const child = (children[i] = normalizeVNode(children[i]));1373 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG);1374 }1375 }1376 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {1377 const el = (n2.el = n1.el);1378 const { patchFlag, dynamicChildren } = n2;1379 const oldProps = (n1 && n1.props) || EMPTY_OBJ;1380 const newProps = n2.props || EMPTY_OBJ;1381 if (newProps.vnodeBeforeUpdate != null) {1382 invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1);1383 }1384 if (patchFlag > 0) {1385 // the presence of a patchFlag means this element's render code was1386 // generated by the compiler and can take the fast path.1387 // in this path old node and new node are guaranteed to have the same shape1388 // (i.e. at the exact same position in the source template)1389 if (patchFlag & 16 /* FULL_PROPS */) {1390 // element props contain dynamic keys, full diff needed1391 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1392 }1393 else {1394 // class1395 // this flag is matched when the element has dynamic class bindings.1396 if (patchFlag & 2 /* CLASS */) {1397 if (oldProps.class !== newProps.class) {1398 hostPatchProp(el, 'class', newProps.class, null, isSVG);1399 }1400 }1401 // style1402 // this flag is matched when the element has dynamic style bindings1403 if (patchFlag & 4 /* STYLE */) {1404 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);1405 }1406 // props1407 // This flag is matched when the element has dynamic prop/attr bindings1408 // other than class and style. The keys of dynamic prop/attrs are saved for1409 // faster iteration.1410 // Note dynamic keys like :[foo]="bar" will cause this optimization to1411 // bail out and go through a full diff because we need to unset the old key1412 if (patchFlag & 8 /* PROPS */) {1413 // if the flag is present then dynamicProps must be non-null1414 const propsToUpdate = n2.dynamicProps;1415 for (let i = 0; i < propsToUpdate.length; i++) {1416 const key = propsToUpdate[i];1417 const prev = oldProps[key];1418 const next = newProps[key];1419 if (prev !== next) {1420 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);1421 }1422 }1423 }1424 }1425 // text1426 // This flag is matched when the element has only dynamic text children.1427 // this flag is terminal (i.e. skips children diffing).1428 if (patchFlag & 1 /* TEXT */) {1429 if (n1.children !== n2.children) {1430 hostSetElementText(el, n2.children);1431 }1432 return; // terminal1433 }1434 }1435 else if (!optimized) {1436 // unoptimized, full diff1437 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1438 }1439 if (dynamicChildren != null) {1440 // children fast path1441 const oldDynamicChildren = n1.dynamicChildren;1442 for (let i = 0; i < dynamicChildren.length; i++) {1443 patch(oldDynamicChildren[i], dynamicChildren[i], el, null, parentComponent, parentSuspense, isSVG, true);1444 }1445 }1446 else if (!optimized) {1447 // full diff1448 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);1449 }1450 if (newProps.vnodeUpdated != null) {1451 queuePostRenderEffect(() => {1452 invokeDirectiveHook(newProps.vnodeUpdated, parentComponent, n2, n1);1453 }, parentSuspense);1454 }1455 }1456 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {1457 if (oldProps !== newProps) {1458 for (const key in newProps) {1459 if (isReservedProp(key))1460 continue;1461 const next = newProps[key];1462 const prev = oldProps[key];1463 if (next !== prev) {1464 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1465 }1466 }1467 if (oldProps !== EMPTY_OBJ) {1468 for (const key in oldProps) {1469 if (isReservedProp(key))1470 continue;1471 if (!(key in newProps)) {1472 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1473 }1474 }1475 }1476 }1477 }1478 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1479 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));1480 const fragmentEndAnchor = (n2.anchor = n11481 ? n1.anchor1482 : hostCreateComment(''));1483 if (n1 == null) {1484 hostInsert(fragmentStartAnchor, container, anchor);1485 hostInsert(fragmentEndAnchor, container, anchor);1486 // a fragment can only have array children1487 // since they are either generated by the compiler, or implicitly created1488 // from arrays.1489 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG);1490 }1491 else {1492 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);1493 }1494 }1495 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1496 const targetSelector = n2.props && n2.props.target;1497 const { patchFlag, shapeFlag, children } = n2;1498 if (n1 == null) {1499 const target = (n2.target = isString(targetSelector)1500 ? hostQuerySelector(targetSelector)1501 : null);1502 if (target != null) {1503 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1504 hostSetElementText(target, children);1505 }1506 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1507 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG);1508 }1509 }1510 else {1511 warn('Invalid Portal target on mount:', target, `(${typeof target})`);1512 }1513 }1514 else {1515 // update content1516 const target = (n2.target = n1.target);1517 if (patchFlag === 1 /* TEXT */) {1518 hostSetElementText(target, children);1519 }1520 else if (!optimized) {1521 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);1522 }1523 // target changed1524 if (targetSelector !== (n1.props && n1.props.target)) {1525 const nextTarget = (n2.target = isString(targetSelector)1526 ? hostQuerySelector(targetSelector)1527 : null);1528 if (nextTarget != null) {1529 // move content1530 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1531 hostSetElementText(target, '');1532 hostSetElementText(nextTarget, children);1533 }1534 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1535 for (let i = 0; i < children.length; i++) {1536 move(children[i], nextTarget, null);1537 }1538 }1539 }1540 else {1541 warn('Invalid Portal target on update:', target, `(${typeof target})`);1542 }1543 }1544 }1545 // insert an empty node as the placeholder for the portal1546 processCommentNode(n1, n2, container, anchor);1547 }1548 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1549 if (n1 == null) {1550 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1551 }1552 else {1553 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);1554 }1555 }1556 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1557 const hiddenContainer = hostCreateElement('div');1558 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));1559 const { content, fallback } = normalizeSuspenseChildren(n2);1560 suspense.subTree = content;1561 suspense.fallbackTree = fallback;1562 // start mounting the content subtree in an off-dom container1563 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1564 // now check if we have encountered any async deps1565 if (suspense.deps > 0) {1566 // mount the fallback tree1567 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1568 isSVG, optimized);1569 n2.el = fallback.el;1570 }1571 else {1572 // Suspense has no async deps. Just resolve.1573 resolveSuspense(suspense);1574 }1575 }1576 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {1577 const suspense = (n2.suspense = n1.suspense);1578 suspense.vnode = n2;1579 const { content, fallback } = normalizeSuspenseChildren(n2);1580 const oldSubTree = suspense.subTree;1581 const oldFallbackTree = suspense.fallbackTree;1582 if (!suspense.isResolved) {1583 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1584 if (suspense.deps > 0) {1585 // still pending. patch the fallback tree.1586 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1587 isSVG, optimized);1588 n2.el = fallback.el;1589 }1590 // If deps somehow becomes 0 after the patch it means the patch caused an1591 // async dep component to unmount and removed its dep. It will cause the1592 // suspense to resolve and we don't need to do anything here.1593 }1594 else {1595 // just normal patch inner content as a fragment1596 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);1597 n2.el = content.el;1598 }1599 suspense.subTree = content;1600 suspense.fallbackTree = fallback;1601 }1602 function resolveSuspense(suspense) {1603 {1604 if (suspense.isResolved) {1605 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);1606 }1607 if (suspense.isUnmounted) {1608 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);1609 }1610 }1611 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;1612 // this is initial anchor on mount1613 let { anchor } = suspense;1614 // unmount fallback tree1615 if (fallbackTree.el) {1616 // if the fallback tree was mounted, it may have been moved1617 // as part of a parent suspense. get the latest anchor for insertion1618 anchor = getNextHostNode(fallbackTree);1619 unmount(fallbackTree, parentComponent, suspense, true);1620 }1621 // move content from off-dom container to actual container1622 move(subTree, container, anchor);1623 const el = (vnode.el = subTree.el);1624 // suspense as the root node of a component...1625 if (parentComponent && parentComponent.subTree === vnode) {1626 parentComponent.vnode.el = el;1627 updateHOCHostEl(parentComponent, el);1628 }1629 // check if there is a pending parent suspense1630 let parent = suspense.parent;1631 let hasUnresolvedAncestor = false;1632 while (parent) {1633 if (!parent.isResolved) {1634 // found a pending parent suspense, merge buffered post jobs1635 // into that parent1636 parent.effects.push(...effects);1637 hasUnresolvedAncestor = true;1638 break;1639 }1640 parent = parent.parent;1641 }1642 // no pending parent suspense, flush all jobs1643 if (!hasUnresolvedAncestor) {1644 queuePostFlushCb(effects);1645 }1646 suspense.isResolved = true;1647 // invoke @resolve event1648 const onResolve = vnode.props && vnode.props.onResolve;1649 if (isFunction(onResolve)) {1650 onResolve();1651 }1652 }1653 function restartSuspense(suspense) {1654 suspense.isResolved = false;1655 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;1656 // move content tree back to the off-dom container1657 const anchor = getNextHostNode(subTree);1658 move(subTree, hiddenContainer, null);1659 // remount the fallback tree1660 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context1661 isSVG, optimized);1662 const el = (vnode.el = fallbackTree.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 // invoke @suspense event1669 const onSuspense = vnode.props && vnode.props.onSuspense;1670 if (isFunction(onSuspense)) {1671 onSuspense();1672 }1673 }1674 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1675 if (n1 == null) {1676 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);1677 }1678 else {1679 const instance = (n2.component = n1.component);1680 if (shouldUpdateComponent(n1, n2, optimized)) {1681 if (1682 instance.asyncDep &&1683 !instance.asyncResolved) {1684 // async & still pending - just update props and slots1685 // since the component's reactive effect for render isn't set-up yet1686 {1687 pushWarningContext(n2);1688 }1689 updateComponentPreRender(instance, n2);1690 {1691 popWarningContext();1692 }1693 return;1694 }1695 else {1696 // normal update1697 instance.next = n2;1698 // instance.update is the reactive effect runner.1699 instance.update();1700 }1701 }1702 else {1703 // no update needed. just copy over properties1704 n2.component = n1.component;1705 n2.el = n1.el;1706 }1707 }1708 if (n2.ref !== null && parentComponent !== null) {1709 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);1710 }1711 }1712 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {1713 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));1714 {1715 pushWarningContext(initialVNode);1716 }1717 // resolve props and slots for setup context1718 const propsOptions = initialVNode.type.props;1719 resolveProps(instance, initialVNode.props, propsOptions);1720 resolveSlots(instance, initialVNode.children);1721 // setup stateful logic1722 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {1723 setupStatefulComponent(instance, parentSuspense);1724 }1725 // setup() is async. This component relies on async logic to be resolved1726 // before proceeding1727 if ( instance.asyncDep) {1728 if (!parentSuspense) {1729 // TODO handle this properly1730 throw new Error('Async component without a suspense boundary!');1731 }1732 // parent suspense already resolved, need to re-suspense1733 // use queueJob so it's handled synchronously after patching the current1734 // suspense tree1735 if (parentSuspense.isResolved) {1736 queueJob(() => {1737 restartSuspense(parentSuspense);1738 });1739 }1740 parentSuspense.deps++;1741 instance.asyncDep1742 .catch(err => {1743 handleError(err, instance, 0 /* SETUP_FUNCTION */);1744 })1745 .then(asyncSetupResult => {1746 // component may be unmounted before resolve1747 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {1748 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);1749 }1750 });1751 // give it a placeholder1752 const placeholder = (instance.subTree = createVNode(Comment));1753 processCommentNode(null, placeholder, container, anchor);1754 initialVNode.el = placeholder.el;1755 return;1756 }1757 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);1758 {1759 popWarningContext();1760 }1761 }1762 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {1763 parentSuspense.deps--;1764 // retry from this component1765 instance.asyncResolved = true;1766 const { vnode } = instance;1767 {1768 pushWarningContext(vnode);1769 }1770 handleSetupResult(instance, asyncSetupResult, parentSuspense);1771 setupRenderEffect(instance, parentSuspense, vnode, 1772 // component may have been moved before resolve1773 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);1774 updateHOCHostEl(instance, vnode.el);1775 {1776 popWarningContext();1777 }1778 if (parentSuspense.deps === 0) {1779 resolveSuspense(parentSuspense);1780 }1781 }1782 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {1783 // create reactive effect for rendering1784 let mounted = false;1785 instance.update = reactivity.effect(function componentEffect() {1786 if (!mounted) {1787 const subTree = (instance.subTree = renderComponentRoot(instance));1788 // beforeMount hook1789 if (instance.bm !== null) {1790 invokeHooks(instance.bm);1791 }1792 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);1793 initialVNode.el = subTree.el;1794 // mounted hook1795 if (instance.m !== null) {1796 queuePostRenderEffect(instance.m, parentSuspense);1797 }1798 mounted = true;1799 }1800 else {1801 // updateComponent1802 // This is triggered by mutation of component's own state (next: null)1803 // OR parent calling processComponent (next: HostVNode)1804 const { next } = instance;1805 {1806 pushWarningContext(next || instance.vnode);1807 }1808 if (next !== null) {1809 updateComponentPreRender(instance, next);1810 }1811 const prevTree = instance.subTree;1812 const nextTree = (instance.subTree = renderComponentRoot(instance));1813 // beforeUpdate hook1814 if (instance.bu !== null) {1815 invokeHooks(instance.bu);1816 }1817 // reset refs1818 // only needed if previous patch had refs1819 if (instance.refs !== EMPTY_OBJ) {1820 instance.refs = {};1821 }1822 patch(prevTree, nextTree, 1823 // parent may have changed if it's in a portal1824 hostParentNode(prevTree.el), 1825 // anchor may have changed if it's in a fragment1826 getNextHostNode(prevTree), instance, parentSuspense, isSVG);1827 instance.vnode.el = nextTree.el;1828 if (next === null) {1829 // self-triggered update. In case of HOC, update parent component1830 // vnode el. HOC is indicated by parent instance's subTree pointing1831 // to child component's vnode1832 updateHOCHostEl(instance, nextTree.el);1833 }1834 // updated hook1835 if (instance.u !== null) {1836 queuePostRenderEffect(instance.u, parentSuspense);1837 }1838 {1839 popWarningContext();1840 }1841 }1842 }, createDevEffectOptions(instance) );1843 }1844 function updateComponentPreRender(instance, nextVNode) {1845 nextVNode.component = instance;1846 instance.vnode = nextVNode;1847 instance.next = null;1848 resolveProps(instance, nextVNode.props, nextVNode.type.props);1849 resolveSlots(instance, nextVNode.children);1850 }1851 function updateHOCHostEl({ vnode, parent }, el) {1852 while (parent && parent.subTree === vnode) {1853 (vnode = parent.vnode).el = el;1854 parent = parent.parent;1855 }1856 }
...
runtime-core.esm-bundler.js
Source:runtime-core.esm-bundler.js
...1222 fallback: normalizeVNode(null)1223 };1224 }1225}1226function createDevEffectOptions(instance) {1227 return {1228 scheduler: queueJob,1229 onTrack: instance.rtc ? e => invokeHooks(instance.rtc, e) : void 0,1230 onTrigger: instance.rtg ? e => invokeHooks(instance.rtg, e) : void 01231 };1232}1233function isSameType$1(n1, n2) {1234 return n1.type === n2.type && n1.key === n2.key;1235}1236function invokeHooks(hooks, arg) {1237 for (let i = 0; i < hooks.length; i++) {1238 hooks[i](arg);1239 }1240}1241function queuePostRenderEffect(fn, suspense) {1242 if (suspense !== null && !suspense.isResolved) {1243 if (isArray(fn)) {1244 suspense.effects.push(...fn);1245 }1246 else {1247 suspense.effects.push(fn);1248 }1249 }1250 else {1251 queuePostFlushCb(fn);1252 }1253}1254/**1255 * The createRenderer function accepts two generic arguments:1256 * HostNode and HostElement, corresponding to Node and Element types in the1257 * host environment. For example, for runtime-dom, HostNode would be the DOM1258 * `Node` interface and HostElement would be the DOM `Element` interface.1259 *1260 * Custom renderers can pass in the platform specific types like this:1261 *1262 * ``` js1263 * const { render, createApp } = createRenderer<Node, Element>({1264 * patchProp,1265 * ...nodeOps1266 * })1267 * ```1268 */1269function createRenderer(options) {1270 const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, querySelector: hostQuerySelector } = options;1271 function patch(n1, // null means this is a mount1272 n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) {1273 // patching & not same type, unmount old tree1274 if (n1 != null && !isSameType$1(n1, n2)) {1275 anchor = getNextHostNode(n1);1276 unmount(n1, parentComponent, parentSuspense, true);1277 n1 = null;1278 }1279 const { type, shapeFlag } = n2;1280 switch (type) {1281 case Text:1282 processText(n1, n2, container, anchor);1283 break;1284 case Comment:1285 processCommentNode(n1, n2, container, anchor);1286 break;1287 case Fragment:1288 processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1289 break;1290 case Portal:1291 processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1292 break;1293 case Suspense:1294 {1295 processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1296 }1297 break;1298 default:1299 if (shapeFlag & 1 /* ELEMENT */) {1300 processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1301 }1302 else if (shapeFlag & 6 /* COMPONENT */) {1303 processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1304 }1305 else {1306 warn('Invalid HostVNode type:', n2.type, `(${typeof n2.type})`);1307 }1308 }1309 }1310 function processText(n1, n2, container, anchor) {1311 if (n1 == null) {1312 hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);1313 }1314 else {1315 const el = (n2.el = n1.el);1316 if (n2.children !== n1.children) {1317 hostSetText(el, n2.children);1318 }1319 }1320 }1321 function processCommentNode(n1, n2, container, anchor) {1322 if (n1 == null) {1323 hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);1324 }1325 else {1326 // there's no support for dynamic comments1327 n2.el = n1.el;1328 }1329 }1330 function processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1331 if (n1 == null) {1332 mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG);1333 }1334 else {1335 patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);1336 }1337 if (n2.ref !== null && parentComponent !== null) {1338 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.el);1339 }1340 }1341 function mountElement(vnode, container, anchor, parentComponent, parentSuspense, isSVG) {1342 const tag = vnode.type;1343 isSVG = isSVG || tag === 'svg';1344 const el = (vnode.el = hostCreateElement(tag, isSVG));1345 const { props, shapeFlag } = vnode;1346 if (props != null) {1347 for (const key in props) {1348 if (isReservedProp(key))1349 continue;1350 hostPatchProp(el, key, props[key], null, isSVG);1351 }1352 if (props.vnodeBeforeMount != null) {1353 invokeDirectiveHook(props.vnodeBeforeMount, parentComponent, vnode);1354 }1355 }1356 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1357 hostSetElementText(el, vnode.children);1358 }1359 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1360 mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG);1361 }1362 hostInsert(el, container, anchor);1363 if (props != null && props.vnodeMounted != null) {1364 queuePostRenderEffect(() => {1365 invokeDirectiveHook(props.vnodeMounted, parentComponent, vnode);1366 }, parentSuspense);1367 }1368 }1369 function mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, start = 0) {1370 for (let i = start; i < children.length; i++) {1371 const child = (children[i] = normalizeVNode(children[i]));1372 patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG);1373 }1374 }1375 function patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized) {1376 const el = (n2.el = n1.el);1377 const { patchFlag, dynamicChildren } = n2;1378 const oldProps = (n1 && n1.props) || EMPTY_OBJ;1379 const newProps = n2.props || EMPTY_OBJ;1380 if (newProps.vnodeBeforeUpdate != null) {1381 invokeDirectiveHook(newProps.vnodeBeforeUpdate, parentComponent, n2, n1);1382 }1383 if (patchFlag > 0) {1384 // the presence of a patchFlag means this element's render code was1385 // generated by the compiler and can take the fast path.1386 // in this path old node and new node are guaranteed to have the same shape1387 // (i.e. at the exact same position in the source template)1388 if (patchFlag & 16 /* FULL_PROPS */) {1389 // element props contain dynamic keys, full diff needed1390 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1391 }1392 else {1393 // class1394 // this flag is matched when the element has dynamic class bindings.1395 if (patchFlag & 2 /* CLASS */) {1396 if (oldProps.class !== newProps.class) {1397 hostPatchProp(el, 'class', newProps.class, null, isSVG);1398 }1399 }1400 // style1401 // this flag is matched when the element has dynamic style bindings1402 if (patchFlag & 4 /* STYLE */) {1403 hostPatchProp(el, 'style', newProps.style, oldProps.style, isSVG);1404 }1405 // props1406 // This flag is matched when the element has dynamic prop/attr bindings1407 // other than class and style. The keys of dynamic prop/attrs are saved for1408 // faster iteration.1409 // Note dynamic keys like :[foo]="bar" will cause this optimization to1410 // bail out and go through a full diff because we need to unset the old key1411 if (patchFlag & 8 /* PROPS */) {1412 // if the flag is present then dynamicProps must be non-null1413 const propsToUpdate = n2.dynamicProps;1414 for (let i = 0; i < propsToUpdate.length; i++) {1415 const key = propsToUpdate[i];1416 const prev = oldProps[key];1417 const next = newProps[key];1418 if (prev !== next) {1419 hostPatchProp(el, key, next, prev, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);1420 }1421 }1422 }1423 }1424 // text1425 // This flag is matched when the element has only dynamic text children.1426 // this flag is terminal (i.e. skips children diffing).1427 if (patchFlag & 1 /* TEXT */) {1428 if (n1.children !== n2.children) {1429 hostSetElementText(el, n2.children);1430 }1431 return; // terminal1432 }1433 }1434 else if (!optimized) {1435 // unoptimized, full diff1436 patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1437 }1438 if (dynamicChildren != null) {1439 // children fast path1440 const oldDynamicChildren = n1.dynamicChildren;1441 for (let i = 0; i < dynamicChildren.length; i++) {1442 patch(oldDynamicChildren[i], dynamicChildren[i], el, null, parentComponent, parentSuspense, isSVG, true);1443 }1444 }1445 else if (!optimized) {1446 // full diff1447 patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG);1448 }1449 if (newProps.vnodeUpdated != null) {1450 queuePostRenderEffect(() => {1451 invokeDirectiveHook(newProps.vnodeUpdated, parentComponent, n2, n1);1452 }, parentSuspense);1453 }1454 }1455 function patchProps(el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) {1456 if (oldProps !== newProps) {1457 for (const key in newProps) {1458 if (isReservedProp(key))1459 continue;1460 const next = newProps[key];1461 const prev = oldProps[key];1462 if (next !== prev) {1463 hostPatchProp(el, key, next, prev, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1464 }1465 }1466 if (oldProps !== EMPTY_OBJ) {1467 for (const key in oldProps) {1468 if (isReservedProp(key))1469 continue;1470 if (!(key in newProps)) {1471 hostPatchProp(el, key, null, null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);1472 }1473 }1474 }1475 }1476 }1477 function processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1478 const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateComment(''));1479 const fragmentEndAnchor = (n2.anchor = n11480 ? n1.anchor1481 : hostCreateComment(''));1482 if (n1 == null) {1483 hostInsert(fragmentStartAnchor, container, anchor);1484 hostInsert(fragmentEndAnchor, container, anchor);1485 // a fragment can only have array children1486 // since they are either generated by the compiler, or implicitly created1487 // from arrays.1488 mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG);1489 }1490 else {1491 patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);1492 }1493 }1494 function processPortal(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1495 const targetSelector = n2.props && n2.props.target;1496 const { patchFlag, shapeFlag, children } = n2;1497 if (n1 == null) {1498 const target = (n2.target = isString(targetSelector)1499 ? hostQuerySelector(targetSelector)1500 : null);1501 if (target != null) {1502 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1503 hostSetElementText(target, children);1504 }1505 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1506 mountChildren(children, target, null, parentComponent, parentSuspense, isSVG);1507 }1508 }1509 else {1510 warn('Invalid Portal target on mount:', target, `(${typeof target})`);1511 }1512 }1513 else {1514 // update content1515 const target = (n2.target = n1.target);1516 if (patchFlag === 1 /* TEXT */) {1517 hostSetElementText(target, children);1518 }1519 else if (!optimized) {1520 patchChildren(n1, n2, target, null, parentComponent, parentSuspense, isSVG);1521 }1522 // target changed1523 if (targetSelector !== (n1.props && n1.props.target)) {1524 const nextTarget = (n2.target = isString(targetSelector)1525 ? hostQuerySelector(targetSelector)1526 : null);1527 if (nextTarget != null) {1528 // move content1529 if (shapeFlag & 8 /* TEXT_CHILDREN */) {1530 hostSetElementText(target, '');1531 hostSetElementText(nextTarget, children);1532 }1533 else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1534 for (let i = 0; i < children.length; i++) {1535 move(children[i], nextTarget, null);1536 }1537 }1538 }1539 else {1540 warn('Invalid Portal target on update:', target, `(${typeof target})`);1541 }1542 }1543 }1544 // insert an empty node as the placeholder for the portal1545 processCommentNode(n1, n2, container, anchor);1546 }1547 function processSuspense(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1548 if (n1 == null) {1549 mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);1550 }1551 else {1552 patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized);1553 }1554 }1555 function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1556 const hiddenContainer = hostCreateElement('div');1557 const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized));1558 const { content, fallback } = normalizeSuspenseChildren(n2);1559 suspense.subTree = content;1560 suspense.fallbackTree = fallback;1561 // start mounting the content subtree in an off-dom container1562 patch(null, content, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1563 // now check if we have encountered any async deps1564 if (suspense.deps > 0) {1565 // mount the fallback tree1566 patch(null, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1567 isSVG, optimized);1568 n2.el = fallback.el;1569 }1570 else {1571 // Suspense has no async deps. Just resolve.1572 resolveSuspense(suspense);1573 }1574 }1575 function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized) {1576 const suspense = (n2.suspense = n1.suspense);1577 suspense.vnode = n2;1578 const { content, fallback } = normalizeSuspenseChildren(n2);1579 const oldSubTree = suspense.subTree;1580 const oldFallbackTree = suspense.fallbackTree;1581 if (!suspense.isResolved) {1582 patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);1583 if (suspense.deps > 0) {1584 // still pending. patch the fallback tree.1585 patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context1586 isSVG, optimized);1587 n2.el = fallback.el;1588 }1589 // If deps somehow becomes 0 after the patch it means the patch caused an1590 // async dep component to unmount and removed its dep. It will cause the1591 // suspense to resolve and we don't need to do anything here.1592 }1593 else {1594 // just normal patch inner content as a fragment1595 patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);1596 n2.el = content.el;1597 }1598 suspense.subTree = content;1599 suspense.fallbackTree = fallback;1600 }1601 function resolveSuspense(suspense) {1602 {1603 if (suspense.isResolved) {1604 throw new Error(`resolveSuspense() is called on an already resolved suspense boundary.`);1605 }1606 if (suspense.isUnmounted) {1607 throw new Error(`resolveSuspense() is called on an already unmounted suspense boundary.`);1608 }1609 }1610 const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;1611 // this is initial anchor on mount1612 let { anchor } = suspense;1613 // unmount fallback tree1614 if (fallbackTree.el) {1615 // if the fallback tree was mounted, it may have been moved1616 // as part of a parent suspense. get the latest anchor for insertion1617 anchor = getNextHostNode(fallbackTree);1618 unmount(fallbackTree, parentComponent, suspense, true);1619 }1620 // move content from off-dom container to actual container1621 move(subTree, container, anchor);1622 const el = (vnode.el = subTree.el);1623 // suspense as the root node of a component...1624 if (parentComponent && parentComponent.subTree === vnode) {1625 parentComponent.vnode.el = el;1626 updateHOCHostEl(parentComponent, el);1627 }1628 // check if there is a pending parent suspense1629 let parent = suspense.parent;1630 let hasUnresolvedAncestor = false;1631 while (parent) {1632 if (!parent.isResolved) {1633 // found a pending parent suspense, merge buffered post jobs1634 // into that parent1635 parent.effects.push(...effects);1636 hasUnresolvedAncestor = true;1637 break;1638 }1639 parent = parent.parent;1640 }1641 // no pending parent suspense, flush all jobs1642 if (!hasUnresolvedAncestor) {1643 queuePostFlushCb(effects);1644 }1645 suspense.isResolved = true;1646 // invoke @resolve event1647 const onResolve = vnode.props && vnode.props.onResolve;1648 if (isFunction(onResolve)) {1649 onResolve();1650 }1651 }1652 function restartSuspense(suspense) {1653 suspense.isResolved = false;1654 const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;1655 // move content tree back to the off-dom container1656 const anchor = getNextHostNode(subTree);1657 move(subTree, hiddenContainer, null);1658 // remount the fallback tree1659 patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context1660 isSVG, optimized);1661 const el = (vnode.el = fallbackTree.el);1662 // suspense as the root node of a component...1663 if (parentComponent && parentComponent.subTree === vnode) {1664 parentComponent.vnode.el = el;1665 updateHOCHostEl(parentComponent, el);1666 }1667 // invoke @suspense event1668 const onSuspense = vnode.props && vnode.props.onSuspense;1669 if (isFunction(onSuspense)) {1670 onSuspense();1671 }1672 }1673 function processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {1674 if (n1 == null) {1675 mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG);1676 }1677 else {1678 const instance = (n2.component = n1.component);1679 if (shouldUpdateComponent(n1, n2, optimized)) {1680 if (1681 instance.asyncDep &&1682 !instance.asyncResolved) {1683 // async & still pending - just update props and slots1684 // since the component's reactive effect for render isn't set-up yet1685 {1686 pushWarningContext(n2);1687 }1688 updateComponentPreRender(instance, n2);1689 {1690 popWarningContext();1691 }1692 return;1693 }1694 else {1695 // normal update1696 instance.next = n2;1697 // instance.update is the reactive effect runner.1698 instance.update();1699 }1700 }1701 else {1702 // no update needed. just copy over properties1703 n2.component = n1.component;1704 n2.el = n1.el;1705 }1706 }1707 if (n2.ref !== null && parentComponent !== null) {1708 setRef(n2.ref, n1 && n1.ref, parentComponent, n2.component.renderProxy);1709 }1710 }1711 function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {1712 const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent));1713 {1714 pushWarningContext(initialVNode);1715 }1716 // resolve props and slots for setup context1717 const propsOptions = initialVNode.type.props;1718 resolveProps(instance, initialVNode.props, propsOptions);1719 resolveSlots(instance, initialVNode.children);1720 // setup stateful logic1721 if (initialVNode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {1722 setupStatefulComponent(instance, parentSuspense);1723 }1724 // setup() is async. This component relies on async logic to be resolved1725 // before proceeding1726 if ( instance.asyncDep) {1727 if (!parentSuspense) {1728 // TODO handle this properly1729 throw new Error('Async component without a suspense boundary!');1730 }1731 // parent suspense already resolved, need to re-suspense1732 // use queueJob so it's handled synchronously after patching the current1733 // suspense tree1734 if (parentSuspense.isResolved) {1735 queueJob(() => {1736 restartSuspense(parentSuspense);1737 });1738 }1739 parentSuspense.deps++;1740 instance.asyncDep1741 .catch(err => {1742 handleError(err, instance, 0 /* SETUP_FUNCTION */);1743 })1744 .then(asyncSetupResult => {1745 // component may be unmounted before resolve1746 if (!instance.isUnmounted && !parentSuspense.isUnmounted) {1747 retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG);1748 }1749 });1750 // give it a placeholder1751 const placeholder = (instance.subTree = createVNode(Comment));1752 processCommentNode(null, placeholder, container, anchor);1753 initialVNode.el = placeholder.el;1754 return;1755 }1756 setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG);1757 {1758 popWarningContext();1759 }1760 }1761 function retryAsyncComponent(instance, asyncSetupResult, parentSuspense, isSVG) {1762 parentSuspense.deps--;1763 // retry from this component1764 instance.asyncResolved = true;1765 const { vnode } = instance;1766 {1767 pushWarningContext(vnode);1768 }1769 handleSetupResult(instance, asyncSetupResult, parentSuspense);1770 setupRenderEffect(instance, parentSuspense, vnode, 1771 // component may have been moved before resolve1772 hostParentNode(instance.subTree.el), getNextHostNode(instance.subTree), isSVG);1773 updateHOCHostEl(instance, vnode.el);1774 {1775 popWarningContext();1776 }1777 if (parentSuspense.deps === 0) {1778 resolveSuspense(parentSuspense);1779 }1780 }1781 function setupRenderEffect(instance, parentSuspense, initialVNode, container, anchor, isSVG) {1782 // create reactive effect for rendering1783 let mounted = false;1784 instance.update = effect(function componentEffect() {1785 if (!mounted) {1786 const subTree = (instance.subTree = renderComponentRoot(instance));1787 // beforeMount hook1788 if (instance.bm !== null) {1789 invokeHooks(instance.bm);1790 }1791 patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);1792 initialVNode.el = subTree.el;1793 // mounted hook1794 if (instance.m !== null) {1795 queuePostRenderEffect(instance.m, parentSuspense);1796 }1797 mounted = true;1798 }1799 else {1800 // updateComponent1801 // This is triggered by mutation of component's own state (next: null)1802 // OR parent calling processComponent (next: HostVNode)1803 const { next } = instance;1804 {1805 pushWarningContext(next || instance.vnode);1806 }1807 if (next !== null) {1808 updateComponentPreRender(instance, next);1809 }1810 const prevTree = instance.subTree;1811 const nextTree = (instance.subTree = renderComponentRoot(instance));1812 // beforeUpdate hook1813 if (instance.bu !== null) {1814 invokeHooks(instance.bu);1815 }1816 // reset refs1817 // only needed if previous patch had refs1818 if (instance.refs !== EMPTY_OBJ) {1819 instance.refs = {};1820 }1821 patch(prevTree, nextTree, 1822 // parent may have changed if it's in a portal1823 hostParentNode(prevTree.el), 1824 // anchor may have changed if it's in a fragment1825 getNextHostNode(prevTree), instance, parentSuspense, isSVG);1826 instance.vnode.el = nextTree.el;1827 if (next === null) {1828 // self-triggered update. In case of HOC, update parent component1829 // vnode el. HOC is indicated by parent instance's subTree pointing1830 // to child component's vnode1831 updateHOCHostEl(instance, nextTree.el);1832 }1833 // updated hook1834 if (instance.u !== null) {1835 queuePostRenderEffect(instance.u, parentSuspense);1836 }1837 {1838 popWarningContext();1839 }1840 }1841 }, createDevEffectOptions(instance) );1842 }1843 function updateComponentPreRender(instance, nextVNode) {1844 nextVNode.component = instance;1845 instance.vnode = nextVNode;1846 instance.next = null;1847 resolveProps(instance, nextVNode.props, nextVNode.type.props);1848 resolveSlots(instance, nextVNode.children);1849 }1850 function updateHOCHostEl({ vnode, parent }, el) {1851 while (parent && parent.subTree === vnode) {1852 (vnode = parent.vnode).el = el;1853 parent = parent.parent;1854 }1855 }
...
createApp.js
Source:createApp.js
...826 {827 popWarningContext();828 }829 }830 }, createDevEffectOptions(instance) );831 };832 const updateComponentPreRender = (instance, nextVNode, optimized) => {833 nextVNode.component = instance;834 const prevProps = instance.vnode.props;835 instance.vnode = nextVNode;836 instance.next = null;837 updateProps(instance, nextVNode.props, prevProps, optimized);838 updateSlots(instance, nextVNode.children);839 // props update may have triggered pre-flush watchers.840 // flush them before the render update.841 flushPreFlushCbs(undefined, instance.update);842 };843 const patchChildren = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized = false) => {844 const c1 = n1 && n1.children;...
react.js
Source:react.js
...1135 {1136 popWarningContext();1137 }1138 }1139 }, createDevEffectOptions(instance) );1140};1141 function createDevEffectOptions(instance) {1142 return {1143 scheduler: queueJob,1144 allowRecurse: true,1145 onTrack: instance.rtc ? e => invokeArrayFns(instance.rtc, e) : void 0,1146 onTrigger: instance.rtg ? e => invokeArrayFns(instance.rtg, e) : void 01147 };1148 }1149/*1150* computed1151*/1152function applyOptions(instance, options, deferredData = [], deferredWatch = [], asMixin = false) {1153 // ...1154 if (computedOptions) {1155 for (const key in computedOptions) {...
Using AI Code Generation
1const { createDevEffectOptions } = require('playwright/lib/server/playwright');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch(createDevEffectOptions());5 const context = await browser.newContext();6 const page = await context.newPage();7 await browser.close();8})();
Using AI Code Generation
1const playwright = require('playwright');2const { createDevEffectOptions } = require('playwright/lib/server/devtoolsServer');3const { chromium } = playwright;4(async () => {5 const browser = await chromium.launch();6 const context = await browser.newContext();7 const page = await context.newPage();8 const devEffectOptions = createDevEffectOptions({9 });10 await page.close();11 await context.close();12 await browser.close();13})();
Using AI Code Generation
1const { createDevEffectOptions } = require('playwright/lib/server/browserType');2const { chromium } = require('playwright');3const browser = await chromium.launch(createDevEffectOptions({ slowMo: 1000 }));4const context = await browser.newContext();5const page = await context.newPage();6await page.screenshot({ path: 'example.png' });7await browser.close();
Using AI Code Generation
1import { createDevEffectOptions } from "playwright-core/lib/server/supplements/recorder/recorderUtils";2const devEffectOptions = createDevEffectOptions();3const devEffectOptions = createDevEffectOptions({ isRecording: true });4const devEffectOptions = createDevEffectOptions({ isRecording: true, isEditing: true });5const devEffectOptions = createDevEffectOptions({ isRecording: true, isEditing: true, isPlaying: true });6const devEffectOptions = createDevEffectOptions({ isRecording: true, isEditing: true, isPlaying: true, isPaused: true });7import { createDevEffectOptions } from "playwright-core/lib/server/supplements/recorder/recorderUtils";8const devEffectOptions = createDevEffectOptions();9const devEffectOptions = createDevEffectOptions({ isRecording: true });10const devEffectOptions = createDevEffectOptions({ isRecording: true, isEditing: true });11const devEffectOptions = createDevEffectOptions({ isRecording: true, isEditing: true, isPlaying: true });12const devEffectOptions = createDevEffectOptions({ isRecording: true, isEditing: true, isPlaying: true, isPaused: true });13import { createDevEffectOptions } from "playwright-core/lib/server/supplements/recorder/recorderUtils";14const devEffectOptions = createDevEffectOptions();
Using AI Code Generation
1const { createDevEffectOptions } = require('playwright/lib/server/effect');2const { createPlaywright } = require('playwright');3const playwright = createPlaywright();4const browser = await playwright.chromium.launch();5const context = await browser.newContext();6const page = await context.newPage();7const devEffectOptions = createDevEffectOptions({8 viewport: { width: 100, height: 100 },9});10await page.emulate(devEffectOptions);11await page.screenshot({ path: 'example.png' });12await browser.close();13module.exports = {14 launchOptions: {15 },16 contextOptions: {17 viewport: {18 },19 },20 serverOptions: {21 },22 use: {23 },24};25{26 "scripts": {27 },28 "devDependencies": {29 }30}31I am using jest-playwright-preset to run my tests. I am trying to run tests in headless mode. I have set launchOptions: {headless: true} in jest-playwright.config.js. But it doesn't seem to be working. I am still able to see the browser window opening up. I am using the following versions of the packages:
Using AI Code Generation
1const { createDevEffectOptions } = require('@playwright/test/lib/server/devServer');2const devEffectOptions = createDevEffectOptions({ port: 3000, hostname: 'localhost' });3const { createDevServer } = require('@playwright/test/lib/server/devServer');4const devServer = createDevServer(devEffectOptions);5devServer.start();6devServer.stop();7const { createDevServer } = require('@playwright/test/lib/server/devServer');8const devServer = createDevServer();9devServer.start();10const devEffectOptions = devServer.createDevEffectOptions({ port: 3000, hostname: 'localhost' });11devServer.stop();12const { createDevServer } = require('@playwright/test/lib/server/devServer');13const devServer = createDevServer();14devServer.start();15const devEffectOptions = devServer.createDevEffectOptions({ port: 3000, hostname: 'localhost' });16devServer.start();17devServer.stop();18const { createDevServer } = require('@playwright/test/lib/server/devServer');19const devServer = createDevServer();20devServer.start();21const devEffectOptions = devServer.createDevEffectOptions({ port: 3000, hostname: 'localhost' });22devServer.start();23devServer.stop();
Using AI Code Generation
1const { createDevEffectOptions } = require('playwright/lib/server/playwright');2const { chromium } = require('playwright');3const browser = await chromium.launch(createDevEffectOptions());4await browser.close();5const { createDevEffectOptions } = require('playwright/lib/server/playwright');6const { chromium } = require('playwright');7const browser = await chromium.launch(createDevEffectOptions());8await browser.close();
Using AI Code Generation
1const { createDevEffectOptions } = require('playwright-core/lib/server/browserContext');2const { chromium } = require('playwright-core');3const { launch } = require('playwright-core/lib/server/browserType');4const { createBrowserContext } = require('playwright-core/lib/server/chromium');5const { createPlaywright } = require('playwright-core/lib/server/playwright');6const { createPage } = require('playwright-core/lib/server/page');7const { createDeviceDescriptors } = require('playwright-core/lib/server/deviceDescriptors');8const { createPageProxy } = require('playwright-core/lib/server/pageProxy');9const { createSelectOption } = require('playwright-core/lib/server/page');10const { createSelectors } = require('playwright-core/lib/server/selectors');11const { createKeyboard } = require('playwright-core/lib/server/input');12const { createMouse } = require('playwright-core/lib/server/input');13const { createTouchscreen } = require('playwright-core/lib/server/input');14const { createTracing } = require('playwright-core/lib/server/tracing');15const { createCoverage } = require('playwright-core/lib/server/coverage');16const { createDialog } = require('playwright-core/lib/server/dialog');17const { createDownload } = require('playwright-core/lib/server/download');18const { createFileChooser } = require('playwright-core/lib/server/fileChooser');19const { createFrame } = require('playwright-core/lib/server/frame');20const { createFrameTree } = require('playwright-core/lib/server/frameTree');21const { createWorker } = require('playwright-core/lib/server/worker');22const { createNetworkManager } = require('playwright-core/lib/server/network');23const { createNetworkManagerInstrumentation } = require('playwright-core/lib/server/network');24const { createBrowserServer } = require('playwright-core/lib/server/browserServer');25const { createWebSocketTransport } = require('playwright-core/lib/server/webSocketTransport');26const { createHttpServer } = require('playwright-core/lib/server/httpServer');27const { createRouteHandler } = require('playwright-core/lib/server/route');28const { createSocketServer } = require('playwright-core/lib/server/socketServer');29const { createPipeTransport } = require('playwright-core/lib/server/pipeTransport');30const { createProcessLauncher } = require('playwright-core/lib/server/processLauncher');31const { createPlaywrightServer } = require('
Using AI Code Generation
1const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');2const devEffectOptions = createDevEffectOptions();3console.log(devEffectOptions);4const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');5const devEffectOptions = createDevEffectOptions();6console.log(devEffectOptions);7const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');8const devEffectOptions = createDevEffectOptions();9console.log(devEffectOptions);10const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');11const devEffectOptions = createDevEffectOptions();12console.log(devEffectOptions);13const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');14const devEffectOptions = createDevEffectOptions();15console.log(devEffectOptions);16const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');17const devEffectOptions = createDevEffectOptions();18console.log(devEffectOptions);19const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');20const devEffectOptions = createDevEffectOptions();21console.log(devEffectOptions);22const { createDevEffectOptions } = require('playwright-core/lib/server/supplements/recorder/playwrightDevtoolsProtocol');23const devEffectOptions = createDevEffectOptions();24console.log(devEffectOptions);
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!!