Add more animations and attempt CICD fix
Some checks failed
Build and Deploy / build (push) Failing after 10s

This commit is contained in:
Justin Deal 2025-05-03 15:31:48 -07:00
parent ca9cd27acd
commit bd8ed8bc9c
158 changed files with 30600 additions and 355 deletions

View File

@ -24,8 +24,8 @@ jobs:
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v2 uses: pnpm/action-setup@v2
- name: Install rsync - name: Install system dependencies
run: sudo apt-get update && sudo apt-get install -y rsync run: sudo apt-get update && sudo apt-get install -y rsync build-essential libvips-dev
- name: Setup SSH key - name: Setup SSH key
run: | run: |

577
dist/404.html vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/_astro/index.C9I8Lf1I.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

597
dist/about/index.html vendored

File diff suppressed because one or more lines are too long

BIN
dist/android-chrome-192x192.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
dist/android-chrome-512x512.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

File diff suppressed because one or more lines are too long

581
dist/blog/index.html vendored

File diff suppressed because one or more lines are too long

593
dist/blog/jellyfin-at-home/index.html vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/favicons/apple-touch-icon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
dist/favicons/favicon-16x16.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
dist/favicons/favicon-32x32.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
dist/favicons/favicon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

File diff suppressed because one or more lines are too long

603
dist/index.html vendored

File diff suppressed because one or more lines are too long

252
dist/offline.html vendored Normal file
View File

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Offline | Justin Deal</title>
<style>
:root {
--color-bg: #fbf1c7;
--color-text: #3c3836;
--color-accent: #d65d0e;
--color-muted: #7c6f64;
--font-mono: 'IBM Plex Mono', monospace;
--font-display: 'Press Start 2P', monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #282828;
--color-text: #ebdbb2;
--color-accent: #fe8019;
--color-muted: #a89984;
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font-mono);
background-color: var(--color-bg);
color: var(--color-text);
line-height: 1.6;
display: flex;
flex-direction: column;
min-height: 100vh;
padding: 2rem;
}
main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
max-width: 800px;
margin: 0 auto;
}
h1 {
font-family: var(--font-display);
font-size: 2rem;
margin-bottom: 1rem;
color: var(--color-accent);
}
p {
margin-bottom: 1.5rem;
font-size: 1.1rem;
}
.offline-icon {
font-size: 4rem;
margin-bottom: 2rem;
animation: pulse 2s infinite;
}
.button {
display: inline-block;
background-color: var(--color-accent);
color: var(--color-bg);
padding: 0.75rem 1.5rem;
border-radius: 0.25rem;
text-decoration: none;
font-weight: bold;
transition: transform 0.2s, box-shadow 0.2s;
cursor: pointer;
margin-top: 1rem;
}
.button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.cached-pages {
margin-top: 2rem;
text-align: left;
width: 100%;
max-width: 400px;
}
.cached-pages h2 {
font-size: 1.2rem;
margin-bottom: 1rem;
color: var(--color-accent);
}
.cached-pages ul {
list-style: none;
}
.cached-pages li {
margin-bottom: 0.5rem;
}
.cached-pages a {
color: var(--color-text);
text-decoration: none;
border-bottom: 1px solid var(--color-accent);
padding-bottom: 2px;
}
.cached-pages a:hover {
color: var(--color-accent);
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
</style>
</head>
<body>
<main>
<div class="offline-icon">📶</div>
<h1>You're Offline</h1>
<p>It looks like you've lost your internet connection. Some pages may still be available if you've visited them before.</p>
<button class="button" id="retry-button">Retry Connection</button>
<div class="cached-pages" id="cached-pages">
<h2>Available Pages</h2>
<p>Loading cached pages...</p>
<ul id="cached-pages-list"></ul>
</div>
</main>
<script>
// Check if we're actually offline
function checkConnection() {
return navigator.onLine;
}
// Update UI based on connection status
function updateConnectionStatus() {
if (checkConnection()) {
// We're back online, reload the page
window.location.reload();
} else {
// Still offline
document.querySelector('.offline-icon').textContent = '📶';
document.querySelector('h1').textContent = "You're Offline";
}
}
// Listen for online/offline events
window.addEventListener('online', updateConnectionStatus);
window.addEventListener('offline', updateConnectionStatus);
// Retry button
document.getElementById('retry-button').addEventListener('click', () => {
document.querySelector('.offline-icon').textContent = '🔄';
document.querySelector('h1').textContent = "Checking Connection...";
// Try to fetch the homepage
fetch('/')
.then(() => {
// If successful, we're online
window.location.reload();
})
.catch(() => {
// Still offline
updateConnectionStatus();
});
});
// List cached pages if service worker and caches are available
if ('caches' in window && 'serviceWorker' in navigator) {
caches.open('justin-deal-v1')
.then(cache => {
return cache.keys()
.then(requests => {
const cachedPagesList = document.getElementById('cached-pages-list');
if (requests.length === 0) {
document.getElementById('cached-pages').innerHTML = '<h2>No Cached Pages Available</h2><p>Try visiting some pages when you\'re back online.</p>';
return;
}
// Filter for HTML pages
const htmlRequests = requests.filter(request => {
const url = new URL(request.url);
return url.pathname === '/' ||
url.pathname.endsWith('.html') ||
!url.pathname.includes('.');
});
// Sort by URL
htmlRequests.sort((a, b) => {
return new URL(a.url).pathname.localeCompare(new URL(b.url).pathname);
});
// Create list items
const listItems = htmlRequests.map(request => {
const url = new URL(request.url);
let pageName = url.pathname === '/' ? 'Home' : url.pathname
.replace(/\/$/, '')
.replace(/^\//, '')
.replace(/\.html$/, '')
.split('/')
.pop()
.replace(/-/g, ' ');
// Capitalize first letter of each word
pageName = pageName
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
return `<li><a href="${url.pathname}">${pageName}</a></li>`;
});
if (listItems.length === 0) {
document.getElementById('cached-pages').innerHTML = '<h2>No Cached Pages Available</h2><p>Try visiting some pages when you\'re back online.</p>';
return;
}
cachedPagesList.innerHTML = listItems.join('');
document.querySelector('#cached-pages p').style.display = 'none';
});
})
.catch(error => {
console.error('Error accessing cache:', error);
document.getElementById('cached-pages').innerHTML = '<h2>Could Not Access Cache</h2><p>There was an error accessing the cached pages.</p>';
});
} else {
document.getElementById('cached-pages').innerHTML = '<h2>Cache Not Available</h2><p>Your browser does not support caching or service workers.</p>';
}
</script>
</body>
</html>

0
dist/patterns/light-pattern.svg vendored Normal file
View File

File diff suppressed because one or more lines are too long

637
dist/projects/this-site/index.html vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,47 +0,0 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" type="image/svg+xml" href="/pixel_avatar.png"><meta name="generator" content="Astro v5.7.5"><link rel="preconnect" href="https://fonts.bunny.net"><link href="https://fonts.bunny.net/css?family=ibm-plex-mono:400,400i,500,500i,600,600i,700,700i" rel="stylesheet"> <title>This Website • Justin Deal</title> <meta name="description" content="My personal blog and portfolio, built using TypeScript, TailwindCSS, and Astro."> <meta property="og:title" content="This Website • Justin Deal"> <meta property="og:description" content="My personal blog and portfolio, built using TypeScript, TailwindCSS, and Astro."> <meta property="og:image" content="https://justin.deal/pixel_avatar.png"> <meta property="og:url" content="/projects/zaggonaut"> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="This Website • Justin Deal"> <meta name="twitter:description" content="My personal blog and portfolio, built using TypeScript, TailwindCSS, and Astro."> <meta name="twitter:image" content="https://justin.deal/pixel_avatar.png"> <meta http-equiv="content-language" content="en"> <meta name="language" content="English"> <link rel="canonical" href="https://justin.deal/projects/zaggonaut"> <link rel="stylesheet" href="/_astro/html-intro.CpHT9-yV.css"></head> <body class="zag-bg zag-text zag-transition font-mono"> <header class="zag-bg zag-border-b zag-transition sticky top-0 w-full z-10"> <div class="zag-bg zag-transition sm:hidden relative z-50 py-4 flex items-center"> <button class="px-4" aria-label="Toggle navigation menu"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512" class="zag-fill zag-transition"> <path d="M80 96h352v32H80zm0 144h352v32H80zm0 144h352v32H80z"></path> </svg> </button> </div> <nav class="zag-bg zag-border-b zag-transition fixed sm:relative inset-x-0 top-0 h-auto sm:px-4 flex justify-between flex-col gap-8 py-4 text-xl sm:flex-row max-w-2xl mx-auto sm:pt-4 sm:border-none"> <div class="flex flex-col font-mono font-medium gap-4 sm:flex-row px-4 sm:px-0 mt-16 sm:mt-0"> <a href="/" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> home </a><a href="/blog" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> blog </a><a href="/projects" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> projects </a><a href="/homelab" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> homelab </a> </div> <div class="flex gap-4 justify-between px-4 sm:px-0"> <button class="border-none bg-none focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" id="themeToggle" aria-label="Theme Toggle"> <svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" name="Theme toggle"> <path class="zag-transition fill-neutral-900 dark:fill-transparent" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"></path> <path class="zag-transition fill-transparent dark:fill-neutral-100" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"></path> </svg> </button> <script>
const theme = (() => {
if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
return localStorage.getItem("theme") ?? "light";
}
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
return "light";
})();
if (theme === "light") {
document.documentElement.classList.remove("dark");
} else {
document.documentElement.classList.add("dark");
}
window.localStorage.setItem("theme", theme);
const handleToggleClick = () => {
const element = document.documentElement;
element.classList.toggle("dark");
const isDark = element.classList.contains("dark");
localStorage.setItem("theme", isDark ? "dark" : "light");
};
document
.getElementById("themeToggle")
?.addEventListener("click", handleToggleClick);
</script> </div> </nav> </header> <script type="module">const a=document.querySelector("button"),n=document.querySelector("nav");let t=!1;function e(){window.matchMedia("(max-width: 640px)").matches?n.style.transform=t?"translateY(0)":"translateY(-100%)":(n.style.transform="translateY(0)",t=!1)}function s(){t=!t,e()}a?.addEventListener("click",s);window.addEventListener("resize",e);e();</script> <main> <section class="p-4 max-w-2xl mx-auto mt-8"> <div class="flex flex-col gap-4 mt-8 mb-16"> <h1 class="text-3xl sm:text-4xl leading-tight font-display"> This Website </h1> <div class="flex text-sm gap-2"> <span class="-zag-text -zag-bg zag-transition font-semibold py-1 px-2"> astro </span><span class="-zag-text -zag-bg zag-transition font-semibold py-1 px-2"> typescript </span><span class="-zag-text -zag-bg zag-transition font-semibold py-1 px-2"> web-development </span> </div> <div class="flex gap-2"> <a href="https://code.justin.deal" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light text-base" target="_blank">
GitHub
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 512 512"> <path class="zag-fill zag-transition" fill-rule="evenodd" d="M362.666 149.333V320H320l-.001-97.831l-154.51 154.51l-30.169-30.17L289.829 192h-97.83v-42.666z"></path> </svg> </a> </div> </div> <div class="w-full font-mono prose prose-headings:font-mono prose-img:rounded-none prose-p:text-[var(--color-zag-dark)] prose-p:dark:text-[var(--color-zag-light)] prose-a:underline-offset-4 prose-h1:text-2xl prose-a:text-[var(--color-zag-dark)] dark:prose-a:text-[var(--color-zag-light)] prose-headings:text-[var(--color-zag-dark)] prose-headings:dark:text-[var(--color-zag-light)] prose-p:text-justify prose-code:text-[var(--color-zag-dark)] dark:prose-code:text-[var(--color-zag-light)] prose-h2:text-2xl prose-h3:text-xl prose-h4:text-lg prose-h5:text-base prose-h6:text-sm prose-strong:text-[var(--color-zag-dark)] dark:prose-strong:text-[var(--color-zag-light)] prose-li:text-[var(--color-zag-dark)] dark:prose-li:text-[var(--color-zag-light)] prose-ul:marker:text-[var(--color-zag-dark)] prose-ul:dark:marker:text-[var(--color-zag-light)] prose-ol:marker:text-[var(--color-zag-dark)] prose-ol:dark:marker:text-[var(--color-zag-light)] prose-a:offset-[var(--zag-offset)] prose-a:focus:outline-2 prose-a:focus:outline-offset-2 prose-a:focus:outline-zag-dark prose-a:dark:focus:outline-zag-light"> <h2 id="the-details">The Details</h2>
<p>Zaggonaut is a retro-inspired theme for Astro, built using TypeScript, TailwindCSS, and Astro. Use this theme to power your own personal website, blog, or portfolio with flexibility and customization.</p>
<h2 id="the-features">The Features</h2>
<ul>
<li>Dark &#x26; light mode</li>
<li>Customizable colors</li>
<li>100 / 100 Lighthouse score</li>
<li>Fully accessible</li>
<li>Fully responsive</li>
<li>Type-safe</li>
</ul>
<h2 id="the-future">The Future</h2>
<p>Check out <a href="https://zaggonaut.dev">the theme website</a> to see it in action!</p> </div> </section> </main> <footer class="mt-16 mb-8"> <section class="p-4 max-w-2xl mx-auto mb-4"> <div class="zag-border-b zag-transition pb-4 flex flex-col sm:flex-row sm:flex-nowrap gap-8 sm:items-center"> <ul class="flex flex-row gap-2"> <li> <a href="/" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> home </a> </li><li> <a href="/blog" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> blog </a> </li><li> <a href="/projects" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> projects </a> </li><li> <a href="/homelab" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self"> homelab </a> </li> </ul> <div class="flex flex-row sm:flex-row gap-4"> <a href="https://github.com/RATIU5/zaggonaut" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self" aria-label="GitHub Profile"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"> <path class="zag-fill zag-transition" d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"></path> </svg> </a> <a href="https://twitter.com/" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self" aria-label="Twitter Profile"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"> <path class="zag-fill zag-transition" d="m17.687 3.063l-4.996 5.711l-4.32-5.711H2.112l7.477 9.776l-7.086 8.099h3.034l5.469-6.25l4.78 6.25h6.102l-7.794-10.304l6.625-7.571zm-1.064 16.06L5.654 4.782h1.803l10.846 14.34z"></path> </svg> </a> <a href="https://www.linkedin.com/" class="zag-offset underline font-medium flex items-center focus:outline-2 focus:outline-offset-2 focus:outline-zag-dark dark:focus:outline-zag-light" target="_self" aria-label="LinkedIn Profile"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"> <path class="zag-fill zag-transition" fill="currentColor" d="M19 0h-14c-2.76 0-5 2.24-5 5v14c0 2.76 2.24 5 5 5h14c2.76 0 5-2.24 5-5v-14c0-2.76-2.24-5-5-5zm-11.12 19h-3.08v-9h3.08v9zm-1.54-10.29c-.99 0-1.79-.8-1.79-1.79s.8-1.79 1.79-1.79 1.79.8 1.79 1.79-.8 1.79-1.79 1.79zm13.16 10.29h-3.08v-4.89c0-1.16-.02-2.64-1.61-2.64s-1.86 1.26-1.86 2.57v4.96h-3.08v-9h2.96v1.23h.04c.41-.78 1.4-1.6 2.88-1.6 3.08 0 3.65 2.03 3.65 4.66v4.71z"></path> </svg> </a> </div> </div> </section> <p class="zag-text zag-transition text-center text-sm font-medium">
&copy; 2025 Justin Deal. All rights reserved.
</p> </footer> </body></html>

225
dist/service-worker.js vendored Normal file
View File

@ -0,0 +1,225 @@
/**
* Service Worker for justin.deal
* Provides caching and offline support
*/
const CACHE_NAME = 'justin-deal-v1';
// Assets to cache immediately on service worker install
const PRECACHE_ASSETS = [
'/',
'/index.html',
'/favicon.svg',
'/site.webmanifest',
'/favicons/favicon.png',
'/favicons/apple-touch-icon.png',
'/favicons/favicon-16x16.png',
'/favicons/favicon-32x32.png'
];
// Cache strategies
const CACHE_STRATEGIES = {
// Cache first, falling back to network
CACHE_FIRST: 'cache-first',
// Network first, falling back to cache
NETWORK_FIRST: 'network-first',
// Cache only (no network request)
CACHE_ONLY: 'cache-only',
// Network only (no cache lookup)
NETWORK_ONLY: 'network-only',
// Stale while revalidate (serve from cache, update cache in background)
STALE_WHILE_REVALIDATE: 'stale-while-revalidate'
};
// Route patterns and their corresponding cache strategies
const ROUTE_STRATEGIES = [
// HTML pages - network first
{
pattern: /\.html$|\/$/,
strategy: CACHE_STRATEGIES.NETWORK_FIRST
},
// CSS and JS - stale while revalidate
{
pattern: /\.(css|js)$/,
strategy: CACHE_STRATEGIES.STALE_WHILE_REVALIDATE
},
// Images - cache first
{
pattern: /\.(jpe?g|png|gif|svg|webp|avif)$/,
strategy: CACHE_STRATEGIES.CACHE_FIRST
},
// Fonts - cache first
{
pattern: /\.(woff2?|ttf|otf|eot)$/,
strategy: CACHE_STRATEGIES.CACHE_FIRST
},
// API requests - network first
{
pattern: /\/api\//,
strategy: CACHE_STRATEGIES.NETWORK_FIRST
}
];
// Determine cache strategy for a given URL
function getStrategyForUrl(url) {
const matchedRoute = ROUTE_STRATEGIES.find(route => route.pattern.test(url));
return matchedRoute ? matchedRoute.strategy : CACHE_STRATEGIES.NETWORK_FIRST;
}
// Install event - precache critical assets
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRECACHE_ASSETS))
.then(() => self.skipWaiting())
);
});
// Activate event - clean up old caches
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(cacheName => cacheName !== CACHE_NAME)
.map(cacheName => caches.delete(cacheName))
);
}).then(() => self.clients.claim())
);
});
// Helper function to handle network-first strategy
async function networkFirstStrategy(request) {
try {
// Try network first
const networkResponse = await fetch(request);
// If successful, clone and cache the response
if (networkResponse.ok) {
const cache = await caches.open(CACHE_NAME);
cache.put(request, networkResponse.clone());
}
return networkResponse;
} catch (error) {
// If network fails, try cache
const cachedResponse = await caches.match(request);
if (cachedResponse) {
return cachedResponse;
}
// If no cache, throw error
throw error;
}
}
// Helper function to handle cache-first strategy
async function cacheFirstStrategy(request) {
// Try cache first
const cachedResponse = await caches.match(request);
if (cachedResponse) {
return cachedResponse;
}
// If not in cache, get from network
const networkResponse = await fetch(request);
// Cache the response for future
if (networkResponse.ok) {
const cache = await caches.open(CACHE_NAME);
cache.put(request, networkResponse.clone());
}
return networkResponse;
}
// Helper function to handle stale-while-revalidate strategy
async function staleWhileRevalidateStrategy(request) {
// Try to get from cache
const cachedResponse = await caches.match(request);
// Fetch from network to update cache (don't await)
const fetchPromise = fetch(request)
.then(networkResponse => {
if (networkResponse.ok) {
const cache = caches.open(CACHE_NAME);
cache.then(cache => cache.put(request, networkResponse.clone()));
}
return networkResponse;
})
.catch(error => {
console.error('Failed to fetch and update cache:', error);
});
// Return cached response immediately if available
return cachedResponse || fetchPromise;
}
// Fetch event - handle all fetch requests
self.addEventListener('fetch', event => {
// Skip non-GET requests and browser extensions
if (event.request.method !== 'GET' ||
event.request.url.startsWith('chrome-extension://') ||
event.request.url.includes('extension://')) {
return;
}
// Get the appropriate strategy for this URL
const strategy = getStrategyForUrl(event.request.url);
// Apply the selected strategy
switch (strategy) {
case CACHE_STRATEGIES.NETWORK_FIRST:
event.respondWith(networkFirstStrategy(event.request));
break;
case CACHE_STRATEGIES.CACHE_FIRST:
event.respondWith(cacheFirstStrategy(event.request));
break;
case CACHE_STRATEGIES.STALE_WHILE_REVALIDATE:
event.respondWith(staleWhileRevalidateStrategy(event.request));
break;
case CACHE_STRATEGIES.CACHE_ONLY:
event.respondWith(caches.match(event.request));
break;
case CACHE_STRATEGIES.NETWORK_ONLY:
event.respondWith(fetch(event.request));
break;
default:
// Default to network first
event.respondWith(networkFirstStrategy(event.request));
}
});
// Handle offline fallback
self.addEventListener('fetch', event => {
// Only handle HTML navigation requests that fail
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.catch(() => {
// If fetch fails, return the offline page
return caches.match('/offline.html')
.then(response => {
return response || new Response(
'<html><body><h1>Offline</h1><p>You are currently offline.</p></body></html>',
{
headers: { 'Content-Type': 'text/html' }
}
);
});
})
);
}
});
// Listen for messages from the client
self.addEventListener('message', event => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});

20
dist/site.webmanifest vendored Normal file
View File

@ -0,0 +1,20 @@
{
"name": "Justin Deal",
"short_name": "Justin Deal",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#282828",
"background_color": "#ebdbb2",
"display": "standalone",
"start_url": "/"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1 +1 @@
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.7.5","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://justin.deal\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false},\"legacy\":{\"collections\":false}}"] [["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.7.5","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://justin.deal\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{\"quality\":80,\"formats\":[\"webp\",\"avif\",\"png\",\"jpg\"]}},\"domains\":[],\"remotePatterns\":[]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false},\"legacy\":{\"collections\":false}}"]

4
node_modules/.bin/astro generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/justin/justin_deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/justin/justin_deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/astro@5.7.5_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_rollup@4.40.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../astro/astro.js" "$@" exec "$basedir/node" "$basedir/../astro/astro.js" "$@"

4
node_modules/.bin/browserslist generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/browserslist@4.24.4/node_modules/browserslist/node_modules:/home/justin/justin_deal/node_modules/.pnpm/browserslist@4.24.4/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/browserslist@4.24.4/node_modules/browserslist/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/browserslist@4.24.4/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/browserslist@4.24.4/node_modules/browserslist/node_modules:/home/justin/justin_deal/node_modules/.pnpm/browserslist@4.24.4/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/browserslist@4.24.4/node_modules/browserslist/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/browserslist@4.24.4/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/browserslist@4.24.4/node_modules/browserslist/cli.js" "$@" exec "$basedir/node" "$basedir/../.pnpm/browserslist@4.24.4/node_modules/browserslist/cli.js" "$@"

4
node_modules/.bin/jiti generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/node_modules:/home/justin/justin_deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/node_modules:/home/justin/justin_deal/node_modules/.pnpm/jiti@2.4.2/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/jiti@2.4.2/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/node_modules:/home/justin/justin_deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/node_modules:/home/justin/justin_deal/node_modules/.pnpm/jiti@2.4.2/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/lib/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/jiti@2.4.2/node_modules/jiti/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/jiti@2.4.2/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/jiti@2.4.2/node_modules/jiti/lib/jiti-cli.mjs" "$@" exec "$basedir/node" "$basedir/../.pnpm/jiti@2.4.2/node_modules/jiti/lib/jiti-cli.mjs" "$@"

4
node_modules/.bin/rollup generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/node_modules:/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/node_modules:/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/node_modules:/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/node_modules:/home/justin/justin_deal/node_modules/.pnpm/rollup@4.40.0/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/dist/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules/rollup/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/rollup@4.40.0/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/rollup@4.40.0/node_modules/rollup/dist/bin/rollup" "$@" exec "$basedir/node" "$basedir/../.pnpm/rollup@4.40.0/node_modules/rollup/dist/bin/rollup" "$@"

4
node_modules/.bin/tsc generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsc" "$@" exec "$basedir/node" "$basedir/../.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsc" "$@"

4
node_modules/.bin/tsserver generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/justin_deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsserver" "$@" exec "$basedir/node" "$basedir/../.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsserver" "$@"

4
node_modules/.bin/vite generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/node_modules:/home/justin/justin_deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/bin/node_modules:/home/justin/justin_deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/node_modules:/home/justin/justin_deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/bin/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/bin/vite.js" "$@" exec "$basedir/node" "$basedir/../.pnpm/vite@6.3.3_@types+node@22.15.2_jiti@2.4.2_lightningcss@1.29.2_yaml@2.7.1/node_modules/vite/bin/vite.js" "$@"

4
node_modules/.bin/yaml generated vendored
View File

@ -6,9 +6,9 @@ case `uname` in
esac esac
if [ -z "$NODE_PATH" ]; then if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/yaml@2.7.1/node_modules/yaml/node_modules:/home/justin/justin_deal/node_modules/.pnpm/yaml@2.7.1/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/yaml@2.7.1/node_modules/yaml/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/yaml@2.7.1/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules"
else else
export NODE_PATH="/home/justin/justin_deal/node_modules/.pnpm/yaml@2.7.1/node_modules/yaml/node_modules:/home/justin/justin_deal/node_modules/.pnpm/yaml@2.7.1/node_modules:/home/justin/justin_deal/node_modules/.pnpm/node_modules:$NODE_PATH" export NODE_PATH="/home/justin/projects/websites/justin.deal/node_modules/.pnpm/yaml@2.7.1/node_modules/yaml/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/yaml@2.7.1/node_modules:/home/justin/projects/websites/justin.deal/node_modules/.pnpm/node_modules:$NODE_PATH"
fi fi
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../.pnpm/yaml@2.7.1/node_modules/yaml/bin.mjs" "$@" exec "$basedir/node" "$basedir/../.pnpm/yaml@2.7.1/node_modules/yaml/bin.mjs" "$@"

11
node_modules/.modules.yaml generated vendored
View File

@ -215,6 +215,10 @@ hoistedDependencies:
'@types/unist': private '@types/unist': private
'@ungap/structured-clone@1.3.0': '@ungap/structured-clone@1.3.0':
'@ungap/structured-clone': private '@ungap/structured-clone': private
'@vue/reactivity@3.1.5':
'@vue/reactivity': private
'@vue/shared@3.1.5':
'@vue/shared': private
acorn@8.14.1: acorn@8.14.1:
acorn: private acorn: private
ansi-align@3.0.1: ansi-align@3.0.1:
@ -641,8 +645,6 @@ hoistedDependencies:
rollup: private rollup: private
semver@7.7.1: semver@7.7.1:
semver: private semver: private
sharp@0.33.5:
sharp: private
shiki@3.3.0: shiki@3.3.0:
shiki: private shiki: private
simple-swizzle@0.2.2: simple-swizzle@0.2.2:
@ -765,9 +767,6 @@ hoistedDependencies:
zod: private zod: private
zwitch@2.0.4: zwitch@2.0.4:
zwitch: private zwitch: private
ignoredBuilds:
- esbuild
- sharp
included: included:
dependencies: true dependencies: true
devDependencies: true devDependencies: true
@ -777,7 +776,7 @@ layoutVersion: 5
nodeLinker: isolated nodeLinker: isolated
packageManager: pnpm@10.6.0 packageManager: pnpm@10.6.0
pendingBuilds: [] pendingBuilds: []
prunedAt: Sat, 26 Apr 2025 05:42:30 GMT prunedAt: Sat, 03 May 2025 22:30:43 GMT
publicHoistPattern: [] publicHoistPattern: []
registries: registries:
default: https://registry.npmjs.org/ default: https://registry.npmjs.org/

View File

@ -1,5 +1,5 @@
{ {
"lastValidatedTimestamp": 1745646150252, "lastValidatedTimestamp": 1746311443611,
"projects": {}, "projects": {},
"pnpmfileExists": false, "pnpmfileExists": false,
"settings": { "settings": {

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,19 @@
# @vue/reactivity
## Usage Note
This package is inlined into Global & Browser ESM builds of user-facing renderers (e.g. `@vue/runtime-dom`), but also published as a package that can be used standalone. The standalone build should not be used alongside a pre-bundled build of a user-facing renderer, as they will have different internal storage for reactivity connections. A user-facing renderer should re-export all APIs from this package.
For full exposed APIs, see `src/index.ts`. You can also run `yarn build reactivity --types` from repo root, which will generate an API report at `temp/reactivity.api.md`.
## Credits
The implementation of this module is inspired by the following prior art in the JavaScript ecosystem:
- [Meteor Tracker](https://docs.meteor.com/api/tracker.html)
- [nx-js/observer-util](https://github.com/nx-js/observer-util)
- [salesforce/observable-membrane](https://github.com/salesforce/observable-membrane)
## Caveats
- Built-in objects are not observed except for `Array`, `Map`, `WeakMap`, `Set` and `WeakSet`.

View File

@ -0,0 +1,932 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var shared = require('@vue/shared');
const targetMap = new WeakMap();
const effectStack = [];
let activeEffect;
const ITERATE_KEY = Symbol('iterate' );
const MAP_KEY_ITERATE_KEY = Symbol('Map key iterate' );
function isEffect(fn) {
return fn && fn._isEffect === true;
}
function effect(fn, options = shared.EMPTY_OBJ) {
if (isEffect(fn)) {
fn = fn.raw;
}
const effect = createReactiveEffect(fn, options);
if (!options.lazy) {
effect();
}
return effect;
}
function stop(effect) {
if (effect.active) {
cleanup(effect);
if (effect.options.onStop) {
effect.options.onStop();
}
effect.active = false;
}
}
let uid = 0;
function createReactiveEffect(fn, options) {
const effect = function reactiveEffect() {
if (!effect.active) {
return fn();
}
if (!effectStack.includes(effect)) {
cleanup(effect);
try {
enableTracking();
effectStack.push(effect);
activeEffect = effect;
return fn();
}
finally {
effectStack.pop();
resetTracking();
activeEffect = effectStack[effectStack.length - 1];
}
}
};
effect.id = uid++;
effect.allowRecurse = !!options.allowRecurse;
effect._isEffect = true;
effect.active = true;
effect.raw = fn;
effect.deps = [];
effect.options = options;
return effect;
}
function cleanup(effect) {
const { deps } = effect;
if (deps.length) {
for (let i = 0; i < deps.length; i++) {
deps[i].delete(effect);
}
deps.length = 0;
}
}
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
trackStack.push(shouldTrack);
shouldTrack = false;
}
function enableTracking() {
trackStack.push(shouldTrack);
shouldTrack = true;
}
function resetTracking() {
const last = trackStack.pop();
shouldTrack = last === undefined ? true : last;
}
function track(target, type, key) {
if (!shouldTrack || activeEffect === undefined) {
return;
}
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
activeEffect.deps.push(dep);
if (activeEffect.options.onTrack) {
activeEffect.options.onTrack({
effect: activeEffect,
target,
type,
key
});
}
}
}
function trigger(target, type, key, newValue, oldValue, oldTarget) {
const depsMap = targetMap.get(target);
if (!depsMap) {
// never been tracked
return;
}
const effects = new Set();
const add = (effectsToAdd) => {
if (effectsToAdd) {
effectsToAdd.forEach(effect => {
if (effect !== activeEffect || effect.allowRecurse) {
effects.add(effect);
}
});
}
};
if (type === "clear" /* CLEAR */) {
// collection being cleared
// trigger all effects for target
depsMap.forEach(add);
}
else if (key === 'length' && shared.isArray(target)) {
depsMap.forEach((dep, key) => {
if (key === 'length' || key >= newValue) {
add(dep);
}
});
}
else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
add(depsMap.get(key));
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case "add" /* ADD */:
if (!shared.isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (shared.isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
else if (shared.isIntegerKey(key)) {
// new index added to array -> length changes
add(depsMap.get('length'));
}
break;
case "delete" /* DELETE */:
if (!shared.isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (shared.isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
break;
case "set" /* SET */:
if (shared.isMap(target)) {
add(depsMap.get(ITERATE_KEY));
}
break;
}
}
const run = (effect) => {
if (effect.options.onTrigger) {
effect.options.onTrigger({
effect,
target,
key,
type,
newValue,
oldValue,
oldTarget
});
}
if (effect.options.scheduler) {
effect.options.scheduler(effect);
}
else {
effect();
}
};
effects.forEach(run);
}
const isNonTrackableKeys = /*#__PURE__*/ shared.makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key])
.filter(shared.isSymbol));
const get = /*#__PURE__*/ createGetter();
const shallowGet = /*#__PURE__*/ createGetter(false, true);
const readonlyGet = /*#__PURE__*/ createGetter(true);
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations();
function createArrayInstrumentations() {
const instrumentations = {};
['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
instrumentations[key] = function (...args) {
const arr = toRaw(this);
for (let i = 0, l = this.length; i < l; i++) {
track(arr, "get" /* GET */, i + '');
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args);
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw));
}
else {
return res;
}
};
});
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
instrumentations[key] = function (...args) {
pauseTracking();
const res = toRaw(this)[key].apply(this, args);
resetTracking();
return res;
};
});
return instrumentations;
}
function createGetter(isReadonly = false, shallow = false) {
return function get(target, key, receiver) {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */ &&
receiver ===
(isReadonly
? shallow
? shallowReadonlyMap
: readonlyMap
: shallow
? shallowReactiveMap
: reactiveMap).get(target)) {
return target;
}
const targetIsArray = shared.isArray(target);
if (!isReadonly && targetIsArray && shared.hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver);
}
const res = Reflect.get(target, key, receiver);
if (shared.isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
return res;
}
if (!isReadonly) {
track(target, "get" /* GET */, key);
}
if (shallow) {
return res;
}
if (isRef(res)) {
// ref unwrapping - does not apply for Array + integer key.
const shouldUnwrap = !targetIsArray || !shared.isIntegerKey(key);
return shouldUnwrap ? res.value : res;
}
if (shared.isObject(res)) {
// Convert returned value into a proxy as well. we do the isObject check
// here to avoid invalid value warning. Also need to lazy access readonly
// and reactive here to avoid circular dependency.
return isReadonly ? readonly(res) : reactive(res);
}
return res;
};
}
const set = /*#__PURE__*/ createSetter();
const shallowSet = /*#__PURE__*/ createSetter(true);
function createSetter(shallow = false) {
return function set(target, key, value, receiver) {
let oldValue = target[key];
if (!shallow) {
value = toRaw(value);
oldValue = toRaw(oldValue);
if (!shared.isArray(target) && isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
}
const hadKey = shared.isArray(target) && shared.isIntegerKey(key)
? Number(key) < target.length
: shared.hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
// don't trigger if target is something up in the prototype chain of original
if (target === toRaw(receiver)) {
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (shared.hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
}
return result;
};
}
function deleteProperty(target, key) {
const hadKey = shared.hasOwn(target, key);
const oldValue = target[key];
const result = Reflect.deleteProperty(target, key);
if (result && hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function has(target, key) {
const result = Reflect.has(target, key);
if (!shared.isSymbol(key) || !builtInSymbols.has(key)) {
track(target, "has" /* HAS */, key);
}
return result;
}
function ownKeys(target) {
track(target, "iterate" /* ITERATE */, shared.isArray(target) ? 'length' : ITERATE_KEY);
return Reflect.ownKeys(target);
}
const mutableHandlers = {
get,
set,
deleteProperty,
has,
ownKeys
};
const readonlyHandlers = {
get: readonlyGet,
set(target, key) {
{
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
},
deleteProperty(target, key) {
{
console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
}
};
const shallowReactiveHandlers = /*#__PURE__*/ shared.extend({}, mutableHandlers, {
get: shallowGet,
set: shallowSet
});
// Props handlers are special in the sense that it should not unwrap top-level
// refs (in order to allow refs to be explicitly passed down), but should
// retain the reactivity of the normal readonly object.
const shallowReadonlyHandlers = /*#__PURE__*/ shared.extend({}, readonlyHandlers, {
get: shallowReadonlyGet
});
const toReactive = (value) => shared.isObject(value) ? reactive(value) : value;
const toReadonly = (value) => shared.isObject(value) ? readonly(value) : value;
const toShallow = (value) => value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get$1(target, key, isReadonly = false, isShallow = false) {
// #1772: readonly(reactive(Map)) should return readonly + reactive version
// of the value
target = target["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "get" /* GET */, key);
}
!isReadonly && track(rawTarget, "get" /* GET */, rawKey);
const { has } = getProto(rawTarget);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
if (has.call(rawTarget, key)) {
return wrap(target.get(key));
}
else if (has.call(rawTarget, rawKey)) {
return wrap(target.get(rawKey));
}
else if (target !== rawTarget) {
// #3602 readonly(reactive(Map))
// ensure that the nested reactive `Map` can do tracking for itself
target.get(key);
}
}
function has$1(key, isReadonly = false) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "has" /* HAS */, key);
}
!isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
return key === rawKey
? target.has(key)
: target.has(key) || target.has(rawKey);
}
function size(target, isReadonly = false) {
target = target["__v_raw" /* RAW */];
!isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
return Reflect.get(target, 'size', target);
}
function add(value) {
value = toRaw(value);
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, value);
if (!hadKey) {
target.add(value);
trigger(target, "add" /* ADD */, value, value);
}
return this;
}
function set$1(key, value) {
value = toRaw(value);
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else {
checkIdentityKeys(target, has, key);
}
const oldValue = get.call(target, key);
target.set(key, value);
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (shared.hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
return this;
}
function deleteEntry(key) {
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else {
checkIdentityKeys(target, has, key);
}
const oldValue = get ? get.call(target, key) : undefined;
// forward the operation before queueing reactions
const result = target.delete(key);
if (hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function clear() {
const target = toRaw(this);
const hadItems = target.size !== 0;
const oldTarget = shared.isMap(target)
? new Map(target)
: new Set(target)
;
// forward the operation before queueing reactions
const result = target.clear();
if (hadItems) {
trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
}
return result;
}
function createForEach(isReadonly, isShallow) {
return function forEach(callback, thisArg) {
const observed = this;
const target = observed["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
return target.forEach((value, key) => {
// important: make sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
return callback.call(thisArg, wrap(value), wrap(key), observed);
});
};
}
function createIterableMethod(method, isReadonly, isShallow) {
return function (...args) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const targetIsMap = shared.isMap(rawTarget);
const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
const isKeyOnly = method === 'keys' && targetIsMap;
const innerIterator = target[method](...args);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly &&
track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
// return a wrapped iterator which returns observed versions of the
// values emitted from the real iterator
return {
// iterator protocol
next() {
const { value, done } = innerIterator.next();
return done
? { value, done }
: {
value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
done
};
},
// iterable protocol
[Symbol.iterator]() {
return this;
}
};
};
}
function createReadonlyMethod(type) {
return function (...args) {
{
const key = args[0] ? `on key "${args[0]}" ` : ``;
console.warn(`${shared.capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
}
return type === "delete" /* DELETE */ ? false : this;
};
}
function createInstrumentations() {
const mutableInstrumentations = {
get(key) {
return get$1(this, key);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, false)
};
const shallowInstrumentations = {
get(key) {
return get$1(this, key, false, true);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, true)
};
const readonlyInstrumentations = {
get(key) {
return get$1(this, key, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, false)
};
const shallowReadonlyInstrumentations = {
get(key) {
return get$1(this, key, true, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, true)
};
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
iteratorMethods.forEach(method => {
mutableInstrumentations[method] = createIterableMethod(method, false, false);
readonlyInstrumentations[method] = createIterableMethod(method, true, false);
shallowInstrumentations[method] = createIterableMethod(method, false, true);
shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);
});
return [
mutableInstrumentations,
readonlyInstrumentations,
shallowInstrumentations,
shallowReadonlyInstrumentations
];
}
const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations();
function createInstrumentationGetter(isReadonly, shallow) {
const instrumentations = shallow
? isReadonly
? shallowReadonlyInstrumentations
: shallowInstrumentations
: isReadonly
? readonlyInstrumentations
: mutableInstrumentations;
return (target, key, receiver) => {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */) {
return target;
}
return Reflect.get(shared.hasOwn(instrumentations, key) && key in target
? instrumentations
: target, key, receiver);
};
}
const mutableCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, false)
};
const shallowCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, true)
};
const readonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, false)
};
const shallowReadonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, true)
};
function checkIdentityKeys(target, has, key) {
const rawKey = toRaw(key);
if (rawKey !== key && has.call(target, rawKey)) {
const type = shared.toRawType(target);
console.warn(`Reactive ${type} contains both the raw and reactive ` +
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
`which can lead to inconsistencies. ` +
`Avoid differentiating between the raw and reactive versions ` +
`of an object and only use the reactive version if possible.`);
}
}
const reactiveMap = new WeakMap();
const shallowReactiveMap = new WeakMap();
const readonlyMap = new WeakMap();
const shallowReadonlyMap = new WeakMap();
function targetTypeMap(rawType) {
switch (rawType) {
case 'Object':
case 'Array':
return 1 /* COMMON */;
case 'Map':
case 'Set':
case 'WeakMap':
case 'WeakSet':
return 2 /* COLLECTION */;
default:
return 0 /* INVALID */;
}
}
function getTargetType(value) {
return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
? 0 /* INVALID */
: targetTypeMap(shared.toRawType(value));
}
function reactive(target) {
// if trying to observe a readonly proxy, return the readonly version.
if (target && target["__v_isReadonly" /* IS_READONLY */]) {
return target;
}
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
function shallowReactive(target) {
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
function readonly(target) {
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
}
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
function shallowReadonly(target) {
return createReactiveObject(target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap);
}
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {
if (!shared.isObject(target)) {
{
console.warn(`value cannot be made reactive: ${String(target)}`);
}
return target;
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (target["__v_raw" /* RAW */] &&
!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
return target;
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
// only a whitelist of value types can be observed.
const targetType = getTargetType(target);
if (targetType === 0 /* INVALID */) {
return target;
}
const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
proxyMap.set(target, proxy);
return proxy;
}
function isReactive(value) {
if (isReadonly(value)) {
return isReactive(value["__v_raw" /* RAW */]);
}
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
}
function isReadonly(value) {
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
}
function isProxy(value) {
return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
}
function markRaw(value) {
shared.def(value, "__v_skip" /* SKIP */, true);
return value;
}
const convert = (val) => shared.isObject(val) ? reactive(val) : val;
function isRef(r) {
return Boolean(r && r.__v_isRef === true);
}
function ref(value) {
return createRef(value);
}
function shallowRef(value) {
return createRef(value, true);
}
class RefImpl {
constructor(value, _shallow = false) {
this._shallow = _shallow;
this.__v_isRef = true;
this._rawValue = _shallow ? value : toRaw(value);
this._value = _shallow ? value : convert(value);
}
get value() {
track(toRaw(this), "get" /* GET */, 'value');
return this._value;
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
if (shared.hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = this._shallow ? newVal : convert(newVal);
trigger(toRaw(this), "set" /* SET */, 'value', newVal);
}
}
}
function createRef(rawValue, shallow = false) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
function triggerRef(ref) {
trigger(toRaw(ref), "set" /* SET */, 'value', ref.value );
}
function unref(ref) {
return isRef(ref) ? ref.value : ref;
}
const shallowUnwrapHandlers = {
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
set: (target, key, value, receiver) => {
const oldValue = target[key];
if (isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
else {
return Reflect.set(target, key, value, receiver);
}
}
};
function proxyRefs(objectWithRefs) {
return isReactive(objectWithRefs)
? objectWithRefs
: new Proxy(objectWithRefs, shallowUnwrapHandlers);
}
class CustomRefImpl {
constructor(factory) {
this.__v_isRef = true;
const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
this._get = get;
this._set = set;
}
get value() {
return this._get();
}
set value(newVal) {
this._set(newVal);
}
}
function customRef(factory) {
return new CustomRefImpl(factory);
}
function toRefs(object) {
if (!isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`);
}
const ret = shared.isArray(object) ? new Array(object.length) : {};
for (const key in object) {
ret[key] = toRef(object, key);
}
return ret;
}
class ObjectRefImpl {
constructor(_object, _key) {
this._object = _object;
this._key = _key;
this.__v_isRef = true;
}
get value() {
return this._object[this._key];
}
set value(newVal) {
this._object[this._key] = newVal;
}
}
function toRef(object, key) {
return isRef(object[key])
? object[key]
: new ObjectRefImpl(object, key);
}
class ComputedRefImpl {
constructor(getter, _setter, isReadonly) {
this._setter = _setter;
this._dirty = true;
this.__v_isRef = true;
this.effect = effect(getter, {
lazy: true,
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(toRaw(this), "set" /* SET */, 'value');
}
}
});
this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
}
get value() {
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
const self = toRaw(this);
if (self._dirty) {
self._value = this.effect();
self._dirty = false;
}
track(self, "get" /* GET */, 'value');
return self._value;
}
set value(newValue) {
this._setter(newValue);
}
}
function computed(getterOrOptions) {
let getter;
let setter;
if (shared.isFunction(getterOrOptions)) {
getter = getterOrOptions;
setter = () => {
console.warn('Write operation failed: computed value is readonly');
}
;
}
else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return new ComputedRefImpl(getter, setter, shared.isFunction(getterOrOptions) || !getterOrOptions.set);
}
exports.ITERATE_KEY = ITERATE_KEY;
exports.computed = computed;
exports.customRef = customRef;
exports.effect = effect;
exports.enableTracking = enableTracking;
exports.isProxy = isProxy;
exports.isReactive = isReactive;
exports.isReadonly = isReadonly;
exports.isRef = isRef;
exports.markRaw = markRaw;
exports.pauseTracking = pauseTracking;
exports.proxyRefs = proxyRefs;
exports.reactive = reactive;
exports.readonly = readonly;
exports.ref = ref;
exports.resetTracking = resetTracking;
exports.shallowReactive = shallowReactive;
exports.shallowReadonly = shallowReadonly;
exports.shallowRef = shallowRef;
exports.stop = stop;
exports.toRaw = toRaw;
exports.toRef = toRef;
exports.toRefs = toRefs;
exports.track = track;
exports.trigger = trigger;
exports.triggerRef = triggerRef;
exports.unref = unref;

View File

@ -0,0 +1,873 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var shared = require('@vue/shared');
const targetMap = new WeakMap();
const effectStack = [];
let activeEffect;
const ITERATE_KEY = Symbol('');
const MAP_KEY_ITERATE_KEY = Symbol('');
function isEffect(fn) {
return fn && fn._isEffect === true;
}
function effect(fn, options = shared.EMPTY_OBJ) {
if (isEffect(fn)) {
fn = fn.raw;
}
const effect = createReactiveEffect(fn, options);
if (!options.lazy) {
effect();
}
return effect;
}
function stop(effect) {
if (effect.active) {
cleanup(effect);
if (effect.options.onStop) {
effect.options.onStop();
}
effect.active = false;
}
}
let uid = 0;
function createReactiveEffect(fn, options) {
const effect = function reactiveEffect() {
if (!effect.active) {
return fn();
}
if (!effectStack.includes(effect)) {
cleanup(effect);
try {
enableTracking();
effectStack.push(effect);
activeEffect = effect;
return fn();
}
finally {
effectStack.pop();
resetTracking();
activeEffect = effectStack[effectStack.length - 1];
}
}
};
effect.id = uid++;
effect.allowRecurse = !!options.allowRecurse;
effect._isEffect = true;
effect.active = true;
effect.raw = fn;
effect.deps = [];
effect.options = options;
return effect;
}
function cleanup(effect) {
const { deps } = effect;
if (deps.length) {
for (let i = 0; i < deps.length; i++) {
deps[i].delete(effect);
}
deps.length = 0;
}
}
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
trackStack.push(shouldTrack);
shouldTrack = false;
}
function enableTracking() {
trackStack.push(shouldTrack);
shouldTrack = true;
}
function resetTracking() {
const last = trackStack.pop();
shouldTrack = last === undefined ? true : last;
}
function track(target, type, key) {
if (!shouldTrack || activeEffect === undefined) {
return;
}
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
activeEffect.deps.push(dep);
}
}
function trigger(target, type, key, newValue, oldValue, oldTarget) {
const depsMap = targetMap.get(target);
if (!depsMap) {
// never been tracked
return;
}
const effects = new Set();
const add = (effectsToAdd) => {
if (effectsToAdd) {
effectsToAdd.forEach(effect => {
if (effect !== activeEffect || effect.allowRecurse) {
effects.add(effect);
}
});
}
};
if (type === "clear" /* CLEAR */) {
// collection being cleared
// trigger all effects for target
depsMap.forEach(add);
}
else if (key === 'length' && shared.isArray(target)) {
depsMap.forEach((dep, key) => {
if (key === 'length' || key >= newValue) {
add(dep);
}
});
}
else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
add(depsMap.get(key));
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case "add" /* ADD */:
if (!shared.isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (shared.isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
else if (shared.isIntegerKey(key)) {
// new index added to array -> length changes
add(depsMap.get('length'));
}
break;
case "delete" /* DELETE */:
if (!shared.isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (shared.isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
break;
case "set" /* SET */:
if (shared.isMap(target)) {
add(depsMap.get(ITERATE_KEY));
}
break;
}
}
const run = (effect) => {
if (effect.options.scheduler) {
effect.options.scheduler(effect);
}
else {
effect();
}
};
effects.forEach(run);
}
const isNonTrackableKeys = /*#__PURE__*/ shared.makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key])
.filter(shared.isSymbol));
const get = /*#__PURE__*/ createGetter();
const shallowGet = /*#__PURE__*/ createGetter(false, true);
const readonlyGet = /*#__PURE__*/ createGetter(true);
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations();
function createArrayInstrumentations() {
const instrumentations = {};
['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
instrumentations[key] = function (...args) {
const arr = toRaw(this);
for (let i = 0, l = this.length; i < l; i++) {
track(arr, "get" /* GET */, i + '');
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args);
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw));
}
else {
return res;
}
};
});
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
instrumentations[key] = function (...args) {
pauseTracking();
const res = toRaw(this)[key].apply(this, args);
resetTracking();
return res;
};
});
return instrumentations;
}
function createGetter(isReadonly = false, shallow = false) {
return function get(target, key, receiver) {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */ &&
receiver ===
(isReadonly
? shallow
? shallowReadonlyMap
: readonlyMap
: shallow
? shallowReactiveMap
: reactiveMap).get(target)) {
return target;
}
const targetIsArray = shared.isArray(target);
if (!isReadonly && targetIsArray && shared.hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver);
}
const res = Reflect.get(target, key, receiver);
if (shared.isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
return res;
}
if (!isReadonly) {
track(target, "get" /* GET */, key);
}
if (shallow) {
return res;
}
if (isRef(res)) {
// ref unwrapping - does not apply for Array + integer key.
const shouldUnwrap = !targetIsArray || !shared.isIntegerKey(key);
return shouldUnwrap ? res.value : res;
}
if (shared.isObject(res)) {
// Convert returned value into a proxy as well. we do the isObject check
// here to avoid invalid value warning. Also need to lazy access readonly
// and reactive here to avoid circular dependency.
return isReadonly ? readonly(res) : reactive(res);
}
return res;
};
}
const set = /*#__PURE__*/ createSetter();
const shallowSet = /*#__PURE__*/ createSetter(true);
function createSetter(shallow = false) {
return function set(target, key, value, receiver) {
let oldValue = target[key];
if (!shallow) {
value = toRaw(value);
oldValue = toRaw(oldValue);
if (!shared.isArray(target) && isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
}
const hadKey = shared.isArray(target) && shared.isIntegerKey(key)
? Number(key) < target.length
: shared.hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
// don't trigger if target is something up in the prototype chain of original
if (target === toRaw(receiver)) {
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (shared.hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value);
}
}
return result;
};
}
function deleteProperty(target, key) {
const hadKey = shared.hasOwn(target, key);
target[key];
const result = Reflect.deleteProperty(target, key);
if (result && hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined);
}
return result;
}
function has(target, key) {
const result = Reflect.has(target, key);
if (!shared.isSymbol(key) || !builtInSymbols.has(key)) {
track(target, "has" /* HAS */, key);
}
return result;
}
function ownKeys(target) {
track(target, "iterate" /* ITERATE */, shared.isArray(target) ? 'length' : ITERATE_KEY);
return Reflect.ownKeys(target);
}
const mutableHandlers = {
get,
set,
deleteProperty,
has,
ownKeys
};
const readonlyHandlers = {
get: readonlyGet,
set(target, key) {
return true;
},
deleteProperty(target, key) {
return true;
}
};
const shallowReactiveHandlers = /*#__PURE__*/ shared.extend({}, mutableHandlers, {
get: shallowGet,
set: shallowSet
});
// Props handlers are special in the sense that it should not unwrap top-level
// refs (in order to allow refs to be explicitly passed down), but should
// retain the reactivity of the normal readonly object.
const shallowReadonlyHandlers = /*#__PURE__*/ shared.extend({}, readonlyHandlers, {
get: shallowReadonlyGet
});
const toReactive = (value) => shared.isObject(value) ? reactive(value) : value;
const toReadonly = (value) => shared.isObject(value) ? readonly(value) : value;
const toShallow = (value) => value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get$1(target, key, isReadonly = false, isShallow = false) {
// #1772: readonly(reactive(Map)) should return readonly + reactive version
// of the value
target = target["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "get" /* GET */, key);
}
!isReadonly && track(rawTarget, "get" /* GET */, rawKey);
const { has } = getProto(rawTarget);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
if (has.call(rawTarget, key)) {
return wrap(target.get(key));
}
else if (has.call(rawTarget, rawKey)) {
return wrap(target.get(rawKey));
}
else if (target !== rawTarget) {
// #3602 readonly(reactive(Map))
// ensure that the nested reactive `Map` can do tracking for itself
target.get(key);
}
}
function has$1(key, isReadonly = false) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "has" /* HAS */, key);
}
!isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
return key === rawKey
? target.has(key)
: target.has(key) || target.has(rawKey);
}
function size(target, isReadonly = false) {
target = target["__v_raw" /* RAW */];
!isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
return Reflect.get(target, 'size', target);
}
function add(value) {
value = toRaw(value);
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, value);
if (!hadKey) {
target.add(value);
trigger(target, "add" /* ADD */, value, value);
}
return this;
}
function set$1(key, value) {
value = toRaw(value);
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
const oldValue = get.call(target, key);
target.set(key, value);
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (shared.hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value);
}
return this;
}
function deleteEntry(key) {
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
get ? get.call(target, key) : undefined;
// forward the operation before queueing reactions
const result = target.delete(key);
if (hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined);
}
return result;
}
function clear() {
const target = toRaw(this);
const hadItems = target.size !== 0;
// forward the operation before queueing reactions
const result = target.clear();
if (hadItems) {
trigger(target, "clear" /* CLEAR */, undefined, undefined);
}
return result;
}
function createForEach(isReadonly, isShallow) {
return function forEach(callback, thisArg) {
const observed = this;
const target = observed["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
return target.forEach((value, key) => {
// important: make sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
return callback.call(thisArg, wrap(value), wrap(key), observed);
});
};
}
function createIterableMethod(method, isReadonly, isShallow) {
return function (...args) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const targetIsMap = shared.isMap(rawTarget);
const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
const isKeyOnly = method === 'keys' && targetIsMap;
const innerIterator = target[method](...args);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly &&
track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
// return a wrapped iterator which returns observed versions of the
// values emitted from the real iterator
return {
// iterator protocol
next() {
const { value, done } = innerIterator.next();
return done
? { value, done }
: {
value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
done
};
},
// iterable protocol
[Symbol.iterator]() {
return this;
}
};
};
}
function createReadonlyMethod(type) {
return function (...args) {
return type === "delete" /* DELETE */ ? false : this;
};
}
function createInstrumentations() {
const mutableInstrumentations = {
get(key) {
return get$1(this, key);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, false)
};
const shallowInstrumentations = {
get(key) {
return get$1(this, key, false, true);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, true)
};
const readonlyInstrumentations = {
get(key) {
return get$1(this, key, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, false)
};
const shallowReadonlyInstrumentations = {
get(key) {
return get$1(this, key, true, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, true)
};
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
iteratorMethods.forEach(method => {
mutableInstrumentations[method] = createIterableMethod(method, false, false);
readonlyInstrumentations[method] = createIterableMethod(method, true, false);
shallowInstrumentations[method] = createIterableMethod(method, false, true);
shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);
});
return [
mutableInstrumentations,
readonlyInstrumentations,
shallowInstrumentations,
shallowReadonlyInstrumentations
];
}
const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations();
function createInstrumentationGetter(isReadonly, shallow) {
const instrumentations = shallow
? isReadonly
? shallowReadonlyInstrumentations
: shallowInstrumentations
: isReadonly
? readonlyInstrumentations
: mutableInstrumentations;
return (target, key, receiver) => {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */) {
return target;
}
return Reflect.get(shared.hasOwn(instrumentations, key) && key in target
? instrumentations
: target, key, receiver);
};
}
const mutableCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, false)
};
const shallowCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, true)
};
const readonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, false)
};
const shallowReadonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, true)
};
const reactiveMap = new WeakMap();
const shallowReactiveMap = new WeakMap();
const readonlyMap = new WeakMap();
const shallowReadonlyMap = new WeakMap();
function targetTypeMap(rawType) {
switch (rawType) {
case 'Object':
case 'Array':
return 1 /* COMMON */;
case 'Map':
case 'Set':
case 'WeakMap':
case 'WeakSet':
return 2 /* COLLECTION */;
default:
return 0 /* INVALID */;
}
}
function getTargetType(value) {
return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
? 0 /* INVALID */
: targetTypeMap(shared.toRawType(value));
}
function reactive(target) {
// if trying to observe a readonly proxy, return the readonly version.
if (target && target["__v_isReadonly" /* IS_READONLY */]) {
return target;
}
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
function shallowReactive(target) {
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
function readonly(target) {
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
}
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
function shallowReadonly(target) {
return createReactiveObject(target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap);
}
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {
if (!shared.isObject(target)) {
return target;
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (target["__v_raw" /* RAW */] &&
!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
return target;
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
// only a whitelist of value types can be observed.
const targetType = getTargetType(target);
if (targetType === 0 /* INVALID */) {
return target;
}
const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
proxyMap.set(target, proxy);
return proxy;
}
function isReactive(value) {
if (isReadonly(value)) {
return isReactive(value["__v_raw" /* RAW */]);
}
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
}
function isReadonly(value) {
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
}
function isProxy(value) {
return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
}
function markRaw(value) {
shared.def(value, "__v_skip" /* SKIP */, true);
return value;
}
const convert = (val) => shared.isObject(val) ? reactive(val) : val;
function isRef(r) {
return Boolean(r && r.__v_isRef === true);
}
function ref(value) {
return createRef(value);
}
function shallowRef(value) {
return createRef(value, true);
}
class RefImpl {
constructor(value, _shallow = false) {
this._shallow = _shallow;
this.__v_isRef = true;
this._rawValue = _shallow ? value : toRaw(value);
this._value = _shallow ? value : convert(value);
}
get value() {
track(toRaw(this), "get" /* GET */, 'value');
return this._value;
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
if (shared.hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = this._shallow ? newVal : convert(newVal);
trigger(toRaw(this), "set" /* SET */, 'value', newVal);
}
}
}
function createRef(rawValue, shallow = false) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
function triggerRef(ref) {
trigger(toRaw(ref), "set" /* SET */, 'value', void 0);
}
function unref(ref) {
return isRef(ref) ? ref.value : ref;
}
const shallowUnwrapHandlers = {
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
set: (target, key, value, receiver) => {
const oldValue = target[key];
if (isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
else {
return Reflect.set(target, key, value, receiver);
}
}
};
function proxyRefs(objectWithRefs) {
return isReactive(objectWithRefs)
? objectWithRefs
: new Proxy(objectWithRefs, shallowUnwrapHandlers);
}
class CustomRefImpl {
constructor(factory) {
this.__v_isRef = true;
const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
this._get = get;
this._set = set;
}
get value() {
return this._get();
}
set value(newVal) {
this._set(newVal);
}
}
function customRef(factory) {
return new CustomRefImpl(factory);
}
function toRefs(object) {
const ret = shared.isArray(object) ? new Array(object.length) : {};
for (const key in object) {
ret[key] = toRef(object, key);
}
return ret;
}
class ObjectRefImpl {
constructor(_object, _key) {
this._object = _object;
this._key = _key;
this.__v_isRef = true;
}
get value() {
return this._object[this._key];
}
set value(newVal) {
this._object[this._key] = newVal;
}
}
function toRef(object, key) {
return isRef(object[key])
? object[key]
: new ObjectRefImpl(object, key);
}
class ComputedRefImpl {
constructor(getter, _setter, isReadonly) {
this._setter = _setter;
this._dirty = true;
this.__v_isRef = true;
this.effect = effect(getter, {
lazy: true,
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(toRaw(this), "set" /* SET */, 'value');
}
}
});
this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
}
get value() {
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
const self = toRaw(this);
if (self._dirty) {
self._value = this.effect();
self._dirty = false;
}
track(self, "get" /* GET */, 'value');
return self._value;
}
set value(newValue) {
this._setter(newValue);
}
}
function computed(getterOrOptions) {
let getter;
let setter;
if (shared.isFunction(getterOrOptions)) {
getter = getterOrOptions;
setter = shared.NOOP;
}
else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return new ComputedRefImpl(getter, setter, shared.isFunction(getterOrOptions) || !getterOrOptions.set);
}
exports.ITERATE_KEY = ITERATE_KEY;
exports.computed = computed;
exports.customRef = customRef;
exports.effect = effect;
exports.enableTracking = enableTracking;
exports.isProxy = isProxy;
exports.isReactive = isReactive;
exports.isReadonly = isReadonly;
exports.isRef = isRef;
exports.markRaw = markRaw;
exports.pauseTracking = pauseTracking;
exports.proxyRefs = proxyRefs;
exports.reactive = reactive;
exports.readonly = readonly;
exports.ref = ref;
exports.resetTracking = resetTracking;
exports.shallowReactive = shallowReactive;
exports.shallowReadonly = shallowReadonly;
exports.shallowRef = shallowRef;
exports.stop = stop;
exports.toRaw = toRaw;
exports.toRef = toRef;
exports.toRefs = toRefs;
exports.track = track;
exports.trigger = trigger;
exports.triggerRef = triggerRef;
exports.unref = unref;

View File

@ -0,0 +1,323 @@
declare type BaseTypes = string | number | boolean;
declare type Builtin = Primitive | Function | Date | Error | RegExp;
declare type CollectionTypes = IterableCollections | WeakCollections;
export declare function computed<T>(getter: ComputedGetter<T>): ComputedRef<T>;
export declare function computed<T>(options: WritableComputedOptions<T>): WritableComputedRef<T>;
export declare type ComputedGetter<T> = (ctx?: any) => T;
export declare interface ComputedRef<T = any> extends WritableComputedRef<T> {
readonly value: T;
}
export declare type ComputedSetter<T> = (v: T) => void;
export declare function customRef<T>(factory: CustomRefFactory<T>): Ref<T>;
declare type CustomRefFactory<T> = (track: () => void, trigger: () => void) => {
get: () => T;
set: (value: T) => void;
};
export declare type DebuggerEvent = {
effect: ReactiveEffect;
target: object;
type: TrackOpTypes | TriggerOpTypes;
key: any;
} & DebuggerEventExtraInfo;
declare interface DebuggerEventExtraInfo {
newValue?: any;
oldValue?: any;
oldTarget?: Map<any, any> | Set<any>;
}
export declare type DeepReadonly<T> = T extends Builtin ? T : T extends Map<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends WeakMap<infer K, infer V> ? WeakMap<DeepReadonly<K>, DeepReadonly<V>> : T extends Set<infer U> ? ReadonlySet<DeepReadonly<U>> : T extends ReadonlySet<infer U> ? ReadonlySet<DeepReadonly<U>> : T extends WeakSet<infer U> ? WeakSet<DeepReadonly<U>> : T extends Promise<infer U> ? Promise<DeepReadonly<U>> : T extends {} ? {
readonly [K in keyof T]: DeepReadonly<T[K]>;
} : Readonly<T>;
declare type Dep = Set<ReactiveEffect>;
export declare function effect<T = any>(fn: () => T, options?: ReactiveEffectOptions): ReactiveEffect<T>;
export declare function enableTracking(): void;
export declare function isProxy(value: unknown): boolean;
export declare function isReactive(value: unknown): boolean;
export declare function isReadonly(value: unknown): boolean;
export declare function isRef<T>(r: Ref<T> | unknown): r is Ref<T>;
declare type IterableCollections = Map<any, any> | Set<any>;
export declare const ITERATE_KEY: unique symbol;
export declare function markRaw<T extends object>(value: T): T;
export declare function pauseTracking(): void;
declare type Primitive = string | number | boolean | bigint | symbol | undefined | null;
export declare function proxyRefs<T extends object>(objectWithRefs: T): ShallowUnwrapRef<T>;
/**
* Creates a reactive copy of the original object.
*
* The reactive conversion is "deep"it affects all nested properties. In the
* ES2015 Proxy based implementation, the returned proxy is **not** equal to the
* original object. It is recommended to work exclusively with the reactive
* proxy and avoid relying on the original object.
*
* A reactive object also automatically unwraps refs contained in it, so you
* don't need to use `.value` when accessing and mutating their value:
*
* ```js
* const count = ref(0)
* const obj = reactive({
* count
* })
*
* obj.count++
* obj.count // -> 1
* count.value // -> 1
* ```
*/
export declare function reactive<T extends object>(target: T): UnwrapNestedRefs<T>;
export declare interface ReactiveEffect<T = any> {
(): T;
_isEffect: true;
id: number;
active: boolean;
raw: () => T;
deps: Array<Dep>;
options: ReactiveEffectOptions;
allowRecurse: boolean;
}
export declare interface ReactiveEffectOptions {
lazy?: boolean;
scheduler?: (job: ReactiveEffect) => void;
onTrack?: (event: DebuggerEvent) => void;
onTrigger?: (event: DebuggerEvent) => void;
onStop?: () => void;
/**
* Indicates whether the job is allowed to recursively trigger itself when
* managed by the scheduler.
*
* By default, a job cannot trigger itself because some built-in method calls,
* e.g. Array.prototype.push actually performs reads as well (#1740) which
* can lead to confusing infinite loops.
* The allowed cases are component update functions and watch callbacks.
* Component update functions may update child component props, which in turn
* trigger flush: "pre" watch callbacks that mutates state that the parent
* relies on (#1801). Watch callbacks doesn't track its dependencies so if it
* triggers itself again, it's likely intentional and it is the user's
* responsibility to perform recursive state mutation that eventually
* stabilizes (#1727).
*/
allowRecurse?: boolean;
}
export declare const enum ReactiveFlags {
SKIP = "__v_skip",
IS_REACTIVE = "__v_isReactive",
IS_READONLY = "__v_isReadonly",
RAW = "__v_raw"
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
export declare function readonly<T extends object>(target: T): DeepReadonly<UnwrapNestedRefs<T>>;
export declare interface Ref<T = any> {
value: T;
/**
* Type differentiator only.
* We need this to be in public d.ts but don't want it to show up in IDE
* autocomplete, so we use a private Symbol instead.
*/
[RefSymbol]: true;
/* Excluded from this release type: _shallow */
}
export declare function ref<T extends object>(value: T): ToRef<T>;
export declare function ref<T>(value: T): Ref<UnwrapRef<T>>;
export declare function ref<T = any>(): Ref<T | undefined>;
declare const RefSymbol: unique symbol;
/**
* This is a special exported interface for other packages to declare
* additional types that should bail out for ref unwrapping. For example
* \@vue/runtime-dom can declare it like so in its d.ts:
*
* ``` ts
* declare module '@vue/reactivity' {
* export interface RefUnwrapBailTypes {
* runtimeDOMBailTypes: Node | Window
* }
* }
* ```
*
* Note that api-extractor somehow refuses to include `declare module`
* augmentations in its generated d.ts, so we have to manually append them
* to the final generated d.ts in our build process.
*/
export declare interface RefUnwrapBailTypes {
}
export declare function resetTracking(): void;
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
export declare function shallowReactive<T extends object>(target: T): T;
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
export declare function shallowReadonly<T extends object>(target: T): Readonly<{
[K in keyof T]: UnwrapNestedRefs<T[K]>;
}>;
export declare function shallowRef<T extends object>(value: T): T extends Ref ? T : Ref<T>;
export declare function shallowRef<T>(value: T): Ref<T>;
export declare function shallowRef<T = any>(): Ref<T | undefined>;
export declare type ShallowUnwrapRef<T> = {
[K in keyof T]: T[K] extends Ref<infer V> ? V : T[K] extends Ref<infer V> | undefined ? unknown extends V ? undefined : V | undefined : T[K];
};
declare function stop_2(effect: ReactiveEffect): void;
export { stop_2 as stop }
declare type SymbolExtract<T> = (T extends {
[Symbol.asyncIterator]: infer V;
} ? {
[Symbol.asyncIterator]: V;
} : {}) & (T extends {
[Symbol.hasInstance]: infer V;
} ? {
[Symbol.hasInstance]: V;
} : {}) & (T extends {
[Symbol.isConcatSpreadable]: infer V;
} ? {
[Symbol.isConcatSpreadable]: V;
} : {}) & (T extends {
[Symbol.iterator]: infer V;
} ? {
[Symbol.iterator]: V;
} : {}) & (T extends {
[Symbol.match]: infer V;
} ? {
[Symbol.match]: V;
} : {}) & (T extends {
[Symbol.matchAll]: infer V;
} ? {
[Symbol.matchAll]: V;
} : {}) & (T extends {
[Symbol.replace]: infer V;
} ? {
[Symbol.replace]: V;
} : {}) & (T extends {
[Symbol.search]: infer V;
} ? {
[Symbol.search]: V;
} : {}) & (T extends {
[Symbol.species]: infer V;
} ? {
[Symbol.species]: V;
} : {}) & (T extends {
[Symbol.split]: infer V;
} ? {
[Symbol.split]: V;
} : {}) & (T extends {
[Symbol.toPrimitive]: infer V;
} ? {
[Symbol.toPrimitive]: V;
} : {}) & (T extends {
[Symbol.toStringTag]: infer V;
} ? {
[Symbol.toStringTag]: V;
} : {}) & (T extends {
[Symbol.unscopables]: infer V;
} ? {
[Symbol.unscopables]: V;
} : {});
export declare function toRaw<T>(observed: T): T;
declare type ToRef<T> = [T] extends [Ref] ? T : Ref<UnwrapRef<T>>;
export declare function toRef<T extends object, K extends keyof T>(object: T, key: K): ToRef<T[K]>;
export declare type ToRefs<T = any> = {
[K in keyof T]: T[K] extends Ref ? T[K] : Ref<UnwrapRef<T[K]>>;
};
export declare function toRefs<T extends object>(object: T): ToRefs<T>;
export declare function track(target: object, type: TrackOpTypes, key: unknown): void;
export declare const enum TrackOpTypes {
GET = "get",
HAS = "has",
ITERATE = "iterate"
}
export declare function trigger(target: object, type: TriggerOpTypes, key?: unknown, newValue?: unknown, oldValue?: unknown, oldTarget?: Map<unknown, unknown> | Set<unknown>): void;
export declare const enum TriggerOpTypes {
SET = "set",
ADD = "add",
DELETE = "delete",
CLEAR = "clear"
}
export declare function triggerRef(ref: Ref): void;
export declare function unref<T>(ref: T | Ref<T>): T;
export declare type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRef<T>;
declare type UnwrappedObject<T> = {
[P in keyof T]: UnwrapRef<T[P]>;
} & SymbolExtract<T>;
export declare type UnwrapRef<T> = T extends Ref<infer V> ? UnwrapRefSimple<V> : UnwrapRefSimple<T>;
declare type UnwrapRefSimple<T> = T extends Function | CollectionTypes | BaseTypes | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] ? T : T extends Array<any> ? {
[K in keyof T]: UnwrapRefSimple<T[K]>;
} : T extends object ? UnwrappedObject<T> : T;
declare type WeakCollections = WeakMap<any, any> | WeakSet<any>;
export declare interface WritableComputedOptions<T> {
get: ComputedGetter<T>;
set: ComputedSetter<T>;
}
export declare interface WritableComputedRef<T> extends Ref<T> {
readonly effect: ReactiveEffect<T>;
}
export { }

View File

@ -0,0 +1,959 @@
/**
* Make a map and return a function for checking if a key
* is in that map.
* IMPORTANT: all calls of this function must be prefixed with
* \/\*#\_\_PURE\_\_\*\/
* So that rollup can tree-shake them if necessary.
*/
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
const EMPTY_OBJ = Object.freeze({})
;
Object.freeze([]) ;
const extend = Object.assign;
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const isArray = Array.isArray;
const isMap = (val) => toTypeString(val) === '[object Map]';
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isSymbol = (val) => typeof val === 'symbol';
const isObject = (val) => val !== null && typeof val === 'object';
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
// extract "RawType" from strings like "[object RawType]"
return toTypeString(value).slice(8, -1);
};
const isIntegerKey = (key) => isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key;
const cacheStringFunction = (fn) => {
const cache = Object.create(null);
return ((str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
});
};
/**
* @private
*/
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: false,
value
});
};
const targetMap = new WeakMap();
const effectStack = [];
let activeEffect;
const ITERATE_KEY = Symbol('iterate' );
const MAP_KEY_ITERATE_KEY = Symbol('Map key iterate' );
function isEffect(fn) {
return fn && fn._isEffect === true;
}
function effect(fn, options = EMPTY_OBJ) {
if (isEffect(fn)) {
fn = fn.raw;
}
const effect = createReactiveEffect(fn, options);
if (!options.lazy) {
effect();
}
return effect;
}
function stop(effect) {
if (effect.active) {
cleanup(effect);
if (effect.options.onStop) {
effect.options.onStop();
}
effect.active = false;
}
}
let uid = 0;
function createReactiveEffect(fn, options) {
const effect = function reactiveEffect() {
if (!effect.active) {
return fn();
}
if (!effectStack.includes(effect)) {
cleanup(effect);
try {
enableTracking();
effectStack.push(effect);
activeEffect = effect;
return fn();
}
finally {
effectStack.pop();
resetTracking();
activeEffect = effectStack[effectStack.length - 1];
}
}
};
effect.id = uid++;
effect.allowRecurse = !!options.allowRecurse;
effect._isEffect = true;
effect.active = true;
effect.raw = fn;
effect.deps = [];
effect.options = options;
return effect;
}
function cleanup(effect) {
const { deps } = effect;
if (deps.length) {
for (let i = 0; i < deps.length; i++) {
deps[i].delete(effect);
}
deps.length = 0;
}
}
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
trackStack.push(shouldTrack);
shouldTrack = false;
}
function enableTracking() {
trackStack.push(shouldTrack);
shouldTrack = true;
}
function resetTracking() {
const last = trackStack.pop();
shouldTrack = last === undefined ? true : last;
}
function track(target, type, key) {
if (!shouldTrack || activeEffect === undefined) {
return;
}
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
activeEffect.deps.push(dep);
if (activeEffect.options.onTrack) {
activeEffect.options.onTrack({
effect: activeEffect,
target,
type,
key
});
}
}
}
function trigger(target, type, key, newValue, oldValue, oldTarget) {
const depsMap = targetMap.get(target);
if (!depsMap) {
// never been tracked
return;
}
const effects = new Set();
const add = (effectsToAdd) => {
if (effectsToAdd) {
effectsToAdd.forEach(effect => {
if (effect !== activeEffect || effect.allowRecurse) {
effects.add(effect);
}
});
}
};
if (type === "clear" /* CLEAR */) {
// collection being cleared
// trigger all effects for target
depsMap.forEach(add);
}
else if (key === 'length' && isArray(target)) {
depsMap.forEach((dep, key) => {
if (key === 'length' || key >= newValue) {
add(dep);
}
});
}
else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
add(depsMap.get(key));
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case "add" /* ADD */:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
else if (isIntegerKey(key)) {
// new index added to array -> length changes
add(depsMap.get('length'));
}
break;
case "delete" /* DELETE */:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
break;
case "set" /* SET */:
if (isMap(target)) {
add(depsMap.get(ITERATE_KEY));
}
break;
}
}
const run = (effect) => {
if (effect.options.onTrigger) {
effect.options.onTrigger({
effect,
target,
key,
type,
newValue,
oldValue,
oldTarget
});
}
if (effect.options.scheduler) {
effect.options.scheduler(effect);
}
else {
effect();
}
};
effects.forEach(run);
}
const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key])
.filter(isSymbol));
const get = /*#__PURE__*/ createGetter();
const shallowGet = /*#__PURE__*/ createGetter(false, true);
const readonlyGet = /*#__PURE__*/ createGetter(true);
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations();
function createArrayInstrumentations() {
const instrumentations = {};
['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
instrumentations[key] = function (...args) {
const arr = toRaw(this);
for (let i = 0, l = this.length; i < l; i++) {
track(arr, "get" /* GET */, i + '');
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args);
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw));
}
else {
return res;
}
};
});
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
instrumentations[key] = function (...args) {
pauseTracking();
const res = toRaw(this)[key].apply(this, args);
resetTracking();
return res;
};
});
return instrumentations;
}
function createGetter(isReadonly = false, shallow = false) {
return function get(target, key, receiver) {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */ &&
receiver ===
(isReadonly
? shallow
? shallowReadonlyMap
: readonlyMap
: shallow
? shallowReactiveMap
: reactiveMap).get(target)) {
return target;
}
const targetIsArray = isArray(target);
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver);
}
const res = Reflect.get(target, key, receiver);
if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
return res;
}
if (!isReadonly) {
track(target, "get" /* GET */, key);
}
if (shallow) {
return res;
}
if (isRef(res)) {
// ref unwrapping - does not apply for Array + integer key.
const shouldUnwrap = !targetIsArray || !isIntegerKey(key);
return shouldUnwrap ? res.value : res;
}
if (isObject(res)) {
// Convert returned value into a proxy as well. we do the isObject check
// here to avoid invalid value warning. Also need to lazy access readonly
// and reactive here to avoid circular dependency.
return isReadonly ? readonly(res) : reactive(res);
}
return res;
};
}
const set = /*#__PURE__*/ createSetter();
const shallowSet = /*#__PURE__*/ createSetter(true);
function createSetter(shallow = false) {
return function set(target, key, value, receiver) {
let oldValue = target[key];
if (!shallow) {
value = toRaw(value);
oldValue = toRaw(oldValue);
if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
}
const hadKey = isArray(target) && isIntegerKey(key)
? Number(key) < target.length
: hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
// don't trigger if target is something up in the prototype chain of original
if (target === toRaw(receiver)) {
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
}
return result;
};
}
function deleteProperty(target, key) {
const hadKey = hasOwn(target, key);
const oldValue = target[key];
const result = Reflect.deleteProperty(target, key);
if (result && hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function has(target, key) {
const result = Reflect.has(target, key);
if (!isSymbol(key) || !builtInSymbols.has(key)) {
track(target, "has" /* HAS */, key);
}
return result;
}
function ownKeys(target) {
track(target, "iterate" /* ITERATE */, isArray(target) ? 'length' : ITERATE_KEY);
return Reflect.ownKeys(target);
}
const mutableHandlers = {
get,
set,
deleteProperty,
has,
ownKeys
};
const readonlyHandlers = {
get: readonlyGet,
set(target, key) {
{
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
},
deleteProperty(target, key) {
{
console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
}
};
const shallowReactiveHandlers = /*#__PURE__*/ extend({}, mutableHandlers, {
get: shallowGet,
set: shallowSet
});
// Props handlers are special in the sense that it should not unwrap top-level
// refs (in order to allow refs to be explicitly passed down), but should
// retain the reactivity of the normal readonly object.
const shallowReadonlyHandlers = /*#__PURE__*/ extend({}, readonlyHandlers, {
get: shallowReadonlyGet
});
const toReactive = (value) => isObject(value) ? reactive(value) : value;
const toReadonly = (value) => isObject(value) ? readonly(value) : value;
const toShallow = (value) => value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get$1(target, key, isReadonly = false, isShallow = false) {
// #1772: readonly(reactive(Map)) should return readonly + reactive version
// of the value
target = target["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "get" /* GET */, key);
}
!isReadonly && track(rawTarget, "get" /* GET */, rawKey);
const { has } = getProto(rawTarget);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
if (has.call(rawTarget, key)) {
return wrap(target.get(key));
}
else if (has.call(rawTarget, rawKey)) {
return wrap(target.get(rawKey));
}
else if (target !== rawTarget) {
// #3602 readonly(reactive(Map))
// ensure that the nested reactive `Map` can do tracking for itself
target.get(key);
}
}
function has$1(key, isReadonly = false) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "has" /* HAS */, key);
}
!isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
return key === rawKey
? target.has(key)
: target.has(key) || target.has(rawKey);
}
function size(target, isReadonly = false) {
target = target["__v_raw" /* RAW */];
!isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
return Reflect.get(target, 'size', target);
}
function add(value) {
value = toRaw(value);
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, value);
if (!hadKey) {
target.add(value);
trigger(target, "add" /* ADD */, value, value);
}
return this;
}
function set$1(key, value) {
value = toRaw(value);
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else {
checkIdentityKeys(target, has, key);
}
const oldValue = get.call(target, key);
target.set(key, value);
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
return this;
}
function deleteEntry(key) {
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else {
checkIdentityKeys(target, has, key);
}
const oldValue = get ? get.call(target, key) : undefined;
// forward the operation before queueing reactions
const result = target.delete(key);
if (hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function clear() {
const target = toRaw(this);
const hadItems = target.size !== 0;
const oldTarget = isMap(target)
? new Map(target)
: new Set(target)
;
// forward the operation before queueing reactions
const result = target.clear();
if (hadItems) {
trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
}
return result;
}
function createForEach(isReadonly, isShallow) {
return function forEach(callback, thisArg) {
const observed = this;
const target = observed["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
return target.forEach((value, key) => {
// important: make sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
return callback.call(thisArg, wrap(value), wrap(key), observed);
});
};
}
function createIterableMethod(method, isReadonly, isShallow) {
return function (...args) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const targetIsMap = isMap(rawTarget);
const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
const isKeyOnly = method === 'keys' && targetIsMap;
const innerIterator = target[method](...args);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly &&
track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
// return a wrapped iterator which returns observed versions of the
// values emitted from the real iterator
return {
// iterator protocol
next() {
const { value, done } = innerIterator.next();
return done
? { value, done }
: {
value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
done
};
},
// iterable protocol
[Symbol.iterator]() {
return this;
}
};
};
}
function createReadonlyMethod(type) {
return function (...args) {
{
const key = args[0] ? `on key "${args[0]}" ` : ``;
console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
}
return type === "delete" /* DELETE */ ? false : this;
};
}
function createInstrumentations() {
const mutableInstrumentations = {
get(key) {
return get$1(this, key);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, false)
};
const shallowInstrumentations = {
get(key) {
return get$1(this, key, false, true);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, true)
};
const readonlyInstrumentations = {
get(key) {
return get$1(this, key, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, false)
};
const shallowReadonlyInstrumentations = {
get(key) {
return get$1(this, key, true, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, true)
};
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
iteratorMethods.forEach(method => {
mutableInstrumentations[method] = createIterableMethod(method, false, false);
readonlyInstrumentations[method] = createIterableMethod(method, true, false);
shallowInstrumentations[method] = createIterableMethod(method, false, true);
shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);
});
return [
mutableInstrumentations,
readonlyInstrumentations,
shallowInstrumentations,
shallowReadonlyInstrumentations
];
}
const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations();
function createInstrumentationGetter(isReadonly, shallow) {
const instrumentations = shallow
? isReadonly
? shallowReadonlyInstrumentations
: shallowInstrumentations
: isReadonly
? readonlyInstrumentations
: mutableInstrumentations;
return (target, key, receiver) => {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */) {
return target;
}
return Reflect.get(hasOwn(instrumentations, key) && key in target
? instrumentations
: target, key, receiver);
};
}
const mutableCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, false)
};
const shallowCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, true)
};
const readonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, false)
};
const shallowReadonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, true)
};
function checkIdentityKeys(target, has, key) {
const rawKey = toRaw(key);
if (rawKey !== key && has.call(target, rawKey)) {
const type = toRawType(target);
console.warn(`Reactive ${type} contains both the raw and reactive ` +
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
`which can lead to inconsistencies. ` +
`Avoid differentiating between the raw and reactive versions ` +
`of an object and only use the reactive version if possible.`);
}
}
const reactiveMap = new WeakMap();
const shallowReactiveMap = new WeakMap();
const readonlyMap = new WeakMap();
const shallowReadonlyMap = new WeakMap();
function targetTypeMap(rawType) {
switch (rawType) {
case 'Object':
case 'Array':
return 1 /* COMMON */;
case 'Map':
case 'Set':
case 'WeakMap':
case 'WeakSet':
return 2 /* COLLECTION */;
default:
return 0 /* INVALID */;
}
}
function getTargetType(value) {
return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
? 0 /* INVALID */
: targetTypeMap(toRawType(value));
}
function reactive(target) {
// if trying to observe a readonly proxy, return the readonly version.
if (target && target["__v_isReadonly" /* IS_READONLY */]) {
return target;
}
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
function shallowReactive(target) {
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
function readonly(target) {
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
}
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
function shallowReadonly(target) {
return createReactiveObject(target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap);
}
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {
if (!isObject(target)) {
{
console.warn(`value cannot be made reactive: ${String(target)}`);
}
return target;
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (target["__v_raw" /* RAW */] &&
!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
return target;
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
// only a whitelist of value types can be observed.
const targetType = getTargetType(target);
if (targetType === 0 /* INVALID */) {
return target;
}
const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
proxyMap.set(target, proxy);
return proxy;
}
function isReactive(value) {
if (isReadonly(value)) {
return isReactive(value["__v_raw" /* RAW */]);
}
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
}
function isReadonly(value) {
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
}
function isProxy(value) {
return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
}
function markRaw(value) {
def(value, "__v_skip" /* SKIP */, true);
return value;
}
const convert = (val) => isObject(val) ? reactive(val) : val;
function isRef(r) {
return Boolean(r && r.__v_isRef === true);
}
function ref(value) {
return createRef(value);
}
function shallowRef(value) {
return createRef(value, true);
}
class RefImpl {
constructor(value, _shallow = false) {
this._shallow = _shallow;
this.__v_isRef = true;
this._rawValue = _shallow ? value : toRaw(value);
this._value = _shallow ? value : convert(value);
}
get value() {
track(toRaw(this), "get" /* GET */, 'value');
return this._value;
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = this._shallow ? newVal : convert(newVal);
trigger(toRaw(this), "set" /* SET */, 'value', newVal);
}
}
}
function createRef(rawValue, shallow = false) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
function triggerRef(ref) {
trigger(toRaw(ref), "set" /* SET */, 'value', ref.value );
}
function unref(ref) {
return isRef(ref) ? ref.value : ref;
}
const shallowUnwrapHandlers = {
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
set: (target, key, value, receiver) => {
const oldValue = target[key];
if (isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
else {
return Reflect.set(target, key, value, receiver);
}
}
};
function proxyRefs(objectWithRefs) {
return isReactive(objectWithRefs)
? objectWithRefs
: new Proxy(objectWithRefs, shallowUnwrapHandlers);
}
class CustomRefImpl {
constructor(factory) {
this.__v_isRef = true;
const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
this._get = get;
this._set = set;
}
get value() {
return this._get();
}
set value(newVal) {
this._set(newVal);
}
}
function customRef(factory) {
return new CustomRefImpl(factory);
}
function toRefs(object) {
if (!isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`);
}
const ret = isArray(object) ? new Array(object.length) : {};
for (const key in object) {
ret[key] = toRef(object, key);
}
return ret;
}
class ObjectRefImpl {
constructor(_object, _key) {
this._object = _object;
this._key = _key;
this.__v_isRef = true;
}
get value() {
return this._object[this._key];
}
set value(newVal) {
this._object[this._key] = newVal;
}
}
function toRef(object, key) {
return isRef(object[key])
? object[key]
: new ObjectRefImpl(object, key);
}
class ComputedRefImpl {
constructor(getter, _setter, isReadonly) {
this._setter = _setter;
this._dirty = true;
this.__v_isRef = true;
this.effect = effect(getter, {
lazy: true,
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(toRaw(this), "set" /* SET */, 'value');
}
}
});
this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
}
get value() {
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
const self = toRaw(this);
if (self._dirty) {
self._value = this.effect();
self._dirty = false;
}
track(self, "get" /* GET */, 'value');
return self._value;
}
set value(newValue) {
this._setter(newValue);
}
}
function computed(getterOrOptions) {
let getter;
let setter;
if (isFunction(getterOrOptions)) {
getter = getterOrOptions;
setter = () => {
console.warn('Write operation failed: computed value is readonly');
}
;
}
else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set);
}
export { ITERATE_KEY, computed, customRef, effect, enableTracking, isProxy, isReactive, isReadonly, isRef, markRaw, pauseTracking, proxyRefs, reactive, readonly, ref, resetTracking, shallowReactive, shallowReadonly, shallowRef, stop, toRaw, toRef, toRefs, track, trigger, triggerRef, unref };

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,904 @@
import { EMPTY_OBJ, isArray, isMap, isIntegerKey, isSymbol, extend, hasOwn, isObject, hasChanged, makeMap, capitalize, toRawType, def, isFunction, NOOP } from '@vue/shared';
const targetMap = new WeakMap();
const effectStack = [];
let activeEffect;
const ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'iterate' : '');
const MAP_KEY_ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'Map key iterate' : '');
function isEffect(fn) {
return fn && fn._isEffect === true;
}
function effect(fn, options = EMPTY_OBJ) {
if (isEffect(fn)) {
fn = fn.raw;
}
const effect = createReactiveEffect(fn, options);
if (!options.lazy) {
effect();
}
return effect;
}
function stop(effect) {
if (effect.active) {
cleanup(effect);
if (effect.options.onStop) {
effect.options.onStop();
}
effect.active = false;
}
}
let uid = 0;
function createReactiveEffect(fn, options) {
const effect = function reactiveEffect() {
if (!effect.active) {
return fn();
}
if (!effectStack.includes(effect)) {
cleanup(effect);
try {
enableTracking();
effectStack.push(effect);
activeEffect = effect;
return fn();
}
finally {
effectStack.pop();
resetTracking();
activeEffect = effectStack[effectStack.length - 1];
}
}
};
effect.id = uid++;
effect.allowRecurse = !!options.allowRecurse;
effect._isEffect = true;
effect.active = true;
effect.raw = fn;
effect.deps = [];
effect.options = options;
return effect;
}
function cleanup(effect) {
const { deps } = effect;
if (deps.length) {
for (let i = 0; i < deps.length; i++) {
deps[i].delete(effect);
}
deps.length = 0;
}
}
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
trackStack.push(shouldTrack);
shouldTrack = false;
}
function enableTracking() {
trackStack.push(shouldTrack);
shouldTrack = true;
}
function resetTracking() {
const last = trackStack.pop();
shouldTrack = last === undefined ? true : last;
}
function track(target, type, key) {
if (!shouldTrack || activeEffect === undefined) {
return;
}
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
activeEffect.deps.push(dep);
if ((process.env.NODE_ENV !== 'production') && activeEffect.options.onTrack) {
activeEffect.options.onTrack({
effect: activeEffect,
target,
type,
key
});
}
}
}
function trigger(target, type, key, newValue, oldValue, oldTarget) {
const depsMap = targetMap.get(target);
if (!depsMap) {
// never been tracked
return;
}
const effects = new Set();
const add = (effectsToAdd) => {
if (effectsToAdd) {
effectsToAdd.forEach(effect => {
if (effect !== activeEffect || effect.allowRecurse) {
effects.add(effect);
}
});
}
};
if (type === "clear" /* CLEAR */) {
// collection being cleared
// trigger all effects for target
depsMap.forEach(add);
}
else if (key === 'length' && isArray(target)) {
depsMap.forEach((dep, key) => {
if (key === 'length' || key >= newValue) {
add(dep);
}
});
}
else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
add(depsMap.get(key));
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case "add" /* ADD */:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
else if (isIntegerKey(key)) {
// new index added to array -> length changes
add(depsMap.get('length'));
}
break;
case "delete" /* DELETE */:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
break;
case "set" /* SET */:
if (isMap(target)) {
add(depsMap.get(ITERATE_KEY));
}
break;
}
}
const run = (effect) => {
if ((process.env.NODE_ENV !== 'production') && effect.options.onTrigger) {
effect.options.onTrigger({
effect,
target,
key,
type,
newValue,
oldValue,
oldTarget
});
}
if (effect.options.scheduler) {
effect.options.scheduler(effect);
}
else {
effect();
}
};
effects.forEach(run);
}
const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key])
.filter(isSymbol));
const get = /*#__PURE__*/ createGetter();
const shallowGet = /*#__PURE__*/ createGetter(false, true);
const readonlyGet = /*#__PURE__*/ createGetter(true);
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations();
function createArrayInstrumentations() {
const instrumentations = {};
['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
instrumentations[key] = function (...args) {
const arr = toRaw(this);
for (let i = 0, l = this.length; i < l; i++) {
track(arr, "get" /* GET */, i + '');
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args);
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw));
}
else {
return res;
}
};
});
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
instrumentations[key] = function (...args) {
pauseTracking();
const res = toRaw(this)[key].apply(this, args);
resetTracking();
return res;
};
});
return instrumentations;
}
function createGetter(isReadonly = false, shallow = false) {
return function get(target, key, receiver) {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */ &&
receiver ===
(isReadonly
? shallow
? shallowReadonlyMap
: readonlyMap
: shallow
? shallowReactiveMap
: reactiveMap).get(target)) {
return target;
}
const targetIsArray = isArray(target);
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver);
}
const res = Reflect.get(target, key, receiver);
if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
return res;
}
if (!isReadonly) {
track(target, "get" /* GET */, key);
}
if (shallow) {
return res;
}
if (isRef(res)) {
// ref unwrapping - does not apply for Array + integer key.
const shouldUnwrap = !targetIsArray || !isIntegerKey(key);
return shouldUnwrap ? res.value : res;
}
if (isObject(res)) {
// Convert returned value into a proxy as well. we do the isObject check
// here to avoid invalid value warning. Also need to lazy access readonly
// and reactive here to avoid circular dependency.
return isReadonly ? readonly(res) : reactive(res);
}
return res;
};
}
const set = /*#__PURE__*/ createSetter();
const shallowSet = /*#__PURE__*/ createSetter(true);
function createSetter(shallow = false) {
return function set(target, key, value, receiver) {
let oldValue = target[key];
if (!shallow) {
value = toRaw(value);
oldValue = toRaw(oldValue);
if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
}
const hadKey = isArray(target) && isIntegerKey(key)
? Number(key) < target.length
: hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
// don't trigger if target is something up in the prototype chain of original
if (target === toRaw(receiver)) {
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
}
return result;
};
}
function deleteProperty(target, key) {
const hadKey = hasOwn(target, key);
const oldValue = target[key];
const result = Reflect.deleteProperty(target, key);
if (result && hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function has(target, key) {
const result = Reflect.has(target, key);
if (!isSymbol(key) || !builtInSymbols.has(key)) {
track(target, "has" /* HAS */, key);
}
return result;
}
function ownKeys(target) {
track(target, "iterate" /* ITERATE */, isArray(target) ? 'length' : ITERATE_KEY);
return Reflect.ownKeys(target);
}
const mutableHandlers = {
get,
set,
deleteProperty,
has,
ownKeys
};
const readonlyHandlers = {
get: readonlyGet,
set(target, key) {
if ((process.env.NODE_ENV !== 'production')) {
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
},
deleteProperty(target, key) {
if ((process.env.NODE_ENV !== 'production')) {
console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
}
};
const shallowReactiveHandlers = /*#__PURE__*/ extend({}, mutableHandlers, {
get: shallowGet,
set: shallowSet
});
// Props handlers are special in the sense that it should not unwrap top-level
// refs (in order to allow refs to be explicitly passed down), but should
// retain the reactivity of the normal readonly object.
const shallowReadonlyHandlers = /*#__PURE__*/ extend({}, readonlyHandlers, {
get: shallowReadonlyGet
});
const toReactive = (value) => isObject(value) ? reactive(value) : value;
const toReadonly = (value) => isObject(value) ? readonly(value) : value;
const toShallow = (value) => value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get$1(target, key, isReadonly = false, isShallow = false) {
// #1772: readonly(reactive(Map)) should return readonly + reactive version
// of the value
target = target["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "get" /* GET */, key);
}
!isReadonly && track(rawTarget, "get" /* GET */, rawKey);
const { has } = getProto(rawTarget);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
if (has.call(rawTarget, key)) {
return wrap(target.get(key));
}
else if (has.call(rawTarget, rawKey)) {
return wrap(target.get(rawKey));
}
else if (target !== rawTarget) {
// #3602 readonly(reactive(Map))
// ensure that the nested reactive `Map` can do tracking for itself
target.get(key);
}
}
function has$1(key, isReadonly = false) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "has" /* HAS */, key);
}
!isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
return key === rawKey
? target.has(key)
: target.has(key) || target.has(rawKey);
}
function size(target, isReadonly = false) {
target = target["__v_raw" /* RAW */];
!isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
return Reflect.get(target, 'size', target);
}
function add(value) {
value = toRaw(value);
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, value);
if (!hadKey) {
target.add(value);
trigger(target, "add" /* ADD */, value, value);
}
return this;
}
function set$1(key, value) {
value = toRaw(value);
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else if ((process.env.NODE_ENV !== 'production')) {
checkIdentityKeys(target, has, key);
}
const oldValue = get.call(target, key);
target.set(key, value);
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
return this;
}
function deleteEntry(key) {
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else if ((process.env.NODE_ENV !== 'production')) {
checkIdentityKeys(target, has, key);
}
const oldValue = get ? get.call(target, key) : undefined;
// forward the operation before queueing reactions
const result = target.delete(key);
if (hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function clear() {
const target = toRaw(this);
const hadItems = target.size !== 0;
const oldTarget = (process.env.NODE_ENV !== 'production')
? isMap(target)
? new Map(target)
: new Set(target)
: undefined;
// forward the operation before queueing reactions
const result = target.clear();
if (hadItems) {
trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
}
return result;
}
function createForEach(isReadonly, isShallow) {
return function forEach(callback, thisArg) {
const observed = this;
const target = observed["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
return target.forEach((value, key) => {
// important: make sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
return callback.call(thisArg, wrap(value), wrap(key), observed);
});
};
}
function createIterableMethod(method, isReadonly, isShallow) {
return function (...args) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const targetIsMap = isMap(rawTarget);
const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
const isKeyOnly = method === 'keys' && targetIsMap;
const innerIterator = target[method](...args);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly &&
track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
// return a wrapped iterator which returns observed versions of the
// values emitted from the real iterator
return {
// iterator protocol
next() {
const { value, done } = innerIterator.next();
return done
? { value, done }
: {
value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
done
};
},
// iterable protocol
[Symbol.iterator]() {
return this;
}
};
};
}
function createReadonlyMethod(type) {
return function (...args) {
if ((process.env.NODE_ENV !== 'production')) {
const key = args[0] ? `on key "${args[0]}" ` : ``;
console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
}
return type === "delete" /* DELETE */ ? false : this;
};
}
function createInstrumentations() {
const mutableInstrumentations = {
get(key) {
return get$1(this, key);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, false)
};
const shallowInstrumentations = {
get(key) {
return get$1(this, key, false, true);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, true)
};
const readonlyInstrumentations = {
get(key) {
return get$1(this, key, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, false)
};
const shallowReadonlyInstrumentations = {
get(key) {
return get$1(this, key, true, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, true)
};
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
iteratorMethods.forEach(method => {
mutableInstrumentations[method] = createIterableMethod(method, false, false);
readonlyInstrumentations[method] = createIterableMethod(method, true, false);
shallowInstrumentations[method] = createIterableMethod(method, false, true);
shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);
});
return [
mutableInstrumentations,
readonlyInstrumentations,
shallowInstrumentations,
shallowReadonlyInstrumentations
];
}
const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations();
function createInstrumentationGetter(isReadonly, shallow) {
const instrumentations = shallow
? isReadonly
? shallowReadonlyInstrumentations
: shallowInstrumentations
: isReadonly
? readonlyInstrumentations
: mutableInstrumentations;
return (target, key, receiver) => {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */) {
return target;
}
return Reflect.get(hasOwn(instrumentations, key) && key in target
? instrumentations
: target, key, receiver);
};
}
const mutableCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, false)
};
const shallowCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, true)
};
const readonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, false)
};
const shallowReadonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, true)
};
function checkIdentityKeys(target, has, key) {
const rawKey = toRaw(key);
if (rawKey !== key && has.call(target, rawKey)) {
const type = toRawType(target);
console.warn(`Reactive ${type} contains both the raw and reactive ` +
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
`which can lead to inconsistencies. ` +
`Avoid differentiating between the raw and reactive versions ` +
`of an object and only use the reactive version if possible.`);
}
}
const reactiveMap = new WeakMap();
const shallowReactiveMap = new WeakMap();
const readonlyMap = new WeakMap();
const shallowReadonlyMap = new WeakMap();
function targetTypeMap(rawType) {
switch (rawType) {
case 'Object':
case 'Array':
return 1 /* COMMON */;
case 'Map':
case 'Set':
case 'WeakMap':
case 'WeakSet':
return 2 /* COLLECTION */;
default:
return 0 /* INVALID */;
}
}
function getTargetType(value) {
return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
? 0 /* INVALID */
: targetTypeMap(toRawType(value));
}
function reactive(target) {
// if trying to observe a readonly proxy, return the readonly version.
if (target && target["__v_isReadonly" /* IS_READONLY */]) {
return target;
}
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
function shallowReactive(target) {
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
function readonly(target) {
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
}
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
function shallowReadonly(target) {
return createReactiveObject(target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap);
}
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {
if (!isObject(target)) {
if ((process.env.NODE_ENV !== 'production')) {
console.warn(`value cannot be made reactive: ${String(target)}`);
}
return target;
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (target["__v_raw" /* RAW */] &&
!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
return target;
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
// only a whitelist of value types can be observed.
const targetType = getTargetType(target);
if (targetType === 0 /* INVALID */) {
return target;
}
const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
proxyMap.set(target, proxy);
return proxy;
}
function isReactive(value) {
if (isReadonly(value)) {
return isReactive(value["__v_raw" /* RAW */]);
}
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
}
function isReadonly(value) {
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
}
function isProxy(value) {
return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
}
function markRaw(value) {
def(value, "__v_skip" /* SKIP */, true);
return value;
}
const convert = (val) => isObject(val) ? reactive(val) : val;
function isRef(r) {
return Boolean(r && r.__v_isRef === true);
}
function ref(value) {
return createRef(value);
}
function shallowRef(value) {
return createRef(value, true);
}
class RefImpl {
constructor(value, _shallow = false) {
this._shallow = _shallow;
this.__v_isRef = true;
this._rawValue = _shallow ? value : toRaw(value);
this._value = _shallow ? value : convert(value);
}
get value() {
track(toRaw(this), "get" /* GET */, 'value');
return this._value;
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = this._shallow ? newVal : convert(newVal);
trigger(toRaw(this), "set" /* SET */, 'value', newVal);
}
}
}
function createRef(rawValue, shallow = false) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
function triggerRef(ref) {
trigger(toRaw(ref), "set" /* SET */, 'value', (process.env.NODE_ENV !== 'production') ? ref.value : void 0);
}
function unref(ref) {
return isRef(ref) ? ref.value : ref;
}
const shallowUnwrapHandlers = {
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
set: (target, key, value, receiver) => {
const oldValue = target[key];
if (isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
else {
return Reflect.set(target, key, value, receiver);
}
}
};
function proxyRefs(objectWithRefs) {
return isReactive(objectWithRefs)
? objectWithRefs
: new Proxy(objectWithRefs, shallowUnwrapHandlers);
}
class CustomRefImpl {
constructor(factory) {
this.__v_isRef = true;
const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
this._get = get;
this._set = set;
}
get value() {
return this._get();
}
set value(newVal) {
this._set(newVal);
}
}
function customRef(factory) {
return new CustomRefImpl(factory);
}
function toRefs(object) {
if ((process.env.NODE_ENV !== 'production') && !isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`);
}
const ret = isArray(object) ? new Array(object.length) : {};
for (const key in object) {
ret[key] = toRef(object, key);
}
return ret;
}
class ObjectRefImpl {
constructor(_object, _key) {
this._object = _object;
this._key = _key;
this.__v_isRef = true;
}
get value() {
return this._object[this._key];
}
set value(newVal) {
this._object[this._key] = newVal;
}
}
function toRef(object, key) {
return isRef(object[key])
? object[key]
: new ObjectRefImpl(object, key);
}
class ComputedRefImpl {
constructor(getter, _setter, isReadonly) {
this._setter = _setter;
this._dirty = true;
this.__v_isRef = true;
this.effect = effect(getter, {
lazy: true,
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(toRaw(this), "set" /* SET */, 'value');
}
}
});
this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
}
get value() {
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
const self = toRaw(this);
if (self._dirty) {
self._value = this.effect();
self._dirty = false;
}
track(self, "get" /* GET */, 'value');
return self._value;
}
set value(newValue) {
this._setter(newValue);
}
}
function computed(getterOrOptions) {
let getter;
let setter;
if (isFunction(getterOrOptions)) {
getter = getterOrOptions;
setter = (process.env.NODE_ENV !== 'production')
? () => {
console.warn('Write operation failed: computed value is readonly');
}
: NOOP;
}
else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set);
}
export { ITERATE_KEY, computed, customRef, effect, enableTracking, isProxy, isReactive, isReadonly, isRef, markRaw, pauseTracking, proxyRefs, reactive, readonly, ref, resetTracking, shallowReactive, shallowReadonly, shallowRef, stop, toRaw, toRef, toRefs, track, trigger, triggerRef, unref };

View File

@ -0,0 +1,994 @@
var VueReactivity = (function (exports) {
'use strict';
/**
* Make a map and return a function for checking if a key
* is in that map.
* IMPORTANT: all calls of this function must be prefixed with
* \/\*#\_\_PURE\_\_\*\/
* So that rollup can tree-shake them if necessary.
*/
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
const EMPTY_OBJ = Object.freeze({})
;
Object.freeze([]) ;
const extend = Object.assign;
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const isArray = Array.isArray;
const isMap = (val) => toTypeString(val) === '[object Map]';
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isSymbol = (val) => typeof val === 'symbol';
const isObject = (val) => val !== null && typeof val === 'object';
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
// extract "RawType" from strings like "[object RawType]"
return toTypeString(value).slice(8, -1);
};
const isIntegerKey = (key) => isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key;
const cacheStringFunction = (fn) => {
const cache = Object.create(null);
return ((str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
});
};
/**
* @private
*/
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: false,
value
});
};
const targetMap = new WeakMap();
const effectStack = [];
let activeEffect;
const ITERATE_KEY = Symbol('iterate' );
const MAP_KEY_ITERATE_KEY = Symbol('Map key iterate' );
function isEffect(fn) {
return fn && fn._isEffect === true;
}
function effect(fn, options = EMPTY_OBJ) {
if (isEffect(fn)) {
fn = fn.raw;
}
const effect = createReactiveEffect(fn, options);
if (!options.lazy) {
effect();
}
return effect;
}
function stop(effect) {
if (effect.active) {
cleanup(effect);
if (effect.options.onStop) {
effect.options.onStop();
}
effect.active = false;
}
}
let uid = 0;
function createReactiveEffect(fn, options) {
const effect = function reactiveEffect() {
if (!effect.active) {
return fn();
}
if (!effectStack.includes(effect)) {
cleanup(effect);
try {
enableTracking();
effectStack.push(effect);
activeEffect = effect;
return fn();
}
finally {
effectStack.pop();
resetTracking();
activeEffect = effectStack[effectStack.length - 1];
}
}
};
effect.id = uid++;
effect.allowRecurse = !!options.allowRecurse;
effect._isEffect = true;
effect.active = true;
effect.raw = fn;
effect.deps = [];
effect.options = options;
return effect;
}
function cleanup(effect) {
const { deps } = effect;
if (deps.length) {
for (let i = 0; i < deps.length; i++) {
deps[i].delete(effect);
}
deps.length = 0;
}
}
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
trackStack.push(shouldTrack);
shouldTrack = false;
}
function enableTracking() {
trackStack.push(shouldTrack);
shouldTrack = true;
}
function resetTracking() {
const last = trackStack.pop();
shouldTrack = last === undefined ? true : last;
}
function track(target, type, key) {
if (!shouldTrack || activeEffect === undefined) {
return;
}
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
activeEffect.deps.push(dep);
if (activeEffect.options.onTrack) {
activeEffect.options.onTrack({
effect: activeEffect,
target,
type,
key
});
}
}
}
function trigger(target, type, key, newValue, oldValue, oldTarget) {
const depsMap = targetMap.get(target);
if (!depsMap) {
// never been tracked
return;
}
const effects = new Set();
const add = (effectsToAdd) => {
if (effectsToAdd) {
effectsToAdd.forEach(effect => {
if (effect !== activeEffect || effect.allowRecurse) {
effects.add(effect);
}
});
}
};
if (type === "clear" /* CLEAR */) {
// collection being cleared
// trigger all effects for target
depsMap.forEach(add);
}
else if (key === 'length' && isArray(target)) {
depsMap.forEach((dep, key) => {
if (key === 'length' || key >= newValue) {
add(dep);
}
});
}
else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
add(depsMap.get(key));
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case "add" /* ADD */:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
else if (isIntegerKey(key)) {
// new index added to array -> length changes
add(depsMap.get('length'));
}
break;
case "delete" /* DELETE */:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY));
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY));
}
}
break;
case "set" /* SET */:
if (isMap(target)) {
add(depsMap.get(ITERATE_KEY));
}
break;
}
}
const run = (effect) => {
if (effect.options.onTrigger) {
effect.options.onTrigger({
effect,
target,
key,
type,
newValue,
oldValue,
oldTarget
});
}
if (effect.options.scheduler) {
effect.options.scheduler(effect);
}
else {
effect();
}
};
effects.forEach(run);
}
const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key])
.filter(isSymbol));
const get = /*#__PURE__*/ createGetter();
const shallowGet = /*#__PURE__*/ createGetter(false, true);
const readonlyGet = /*#__PURE__*/ createGetter(true);
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations();
function createArrayInstrumentations() {
const instrumentations = {};
['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
instrumentations[key] = function (...args) {
const arr = toRaw(this);
for (let i = 0, l = this.length; i < l; i++) {
track(arr, "get" /* GET */, i + '');
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args);
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw));
}
else {
return res;
}
};
});
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
instrumentations[key] = function (...args) {
pauseTracking();
const res = toRaw(this)[key].apply(this, args);
resetTracking();
return res;
};
});
return instrumentations;
}
function createGetter(isReadonly = false, shallow = false) {
return function get(target, key, receiver) {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */ &&
receiver ===
(isReadonly
? shallow
? shallowReadonlyMap
: readonlyMap
: shallow
? shallowReactiveMap
: reactiveMap).get(target)) {
return target;
}
const targetIsArray = isArray(target);
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver);
}
const res = Reflect.get(target, key, receiver);
if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
return res;
}
if (!isReadonly) {
track(target, "get" /* GET */, key);
}
if (shallow) {
return res;
}
if (isRef(res)) {
// ref unwrapping - does not apply for Array + integer key.
const shouldUnwrap = !targetIsArray || !isIntegerKey(key);
return shouldUnwrap ? res.value : res;
}
if (isObject(res)) {
// Convert returned value into a proxy as well. we do the isObject check
// here to avoid invalid value warning. Also need to lazy access readonly
// and reactive here to avoid circular dependency.
return isReadonly ? readonly(res) : reactive(res);
}
return res;
};
}
const set = /*#__PURE__*/ createSetter();
const shallowSet = /*#__PURE__*/ createSetter(true);
function createSetter(shallow = false) {
return function set(target, key, value, receiver) {
let oldValue = target[key];
if (!shallow) {
value = toRaw(value);
oldValue = toRaw(oldValue);
if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
}
const hadKey = isArray(target) && isIntegerKey(key)
? Number(key) < target.length
: hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
// don't trigger if target is something up in the prototype chain of original
if (target === toRaw(receiver)) {
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
}
return result;
};
}
function deleteProperty(target, key) {
const hadKey = hasOwn(target, key);
const oldValue = target[key];
const result = Reflect.deleteProperty(target, key);
if (result && hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function has(target, key) {
const result = Reflect.has(target, key);
if (!isSymbol(key) || !builtInSymbols.has(key)) {
track(target, "has" /* HAS */, key);
}
return result;
}
function ownKeys(target) {
track(target, "iterate" /* ITERATE */, isArray(target) ? 'length' : ITERATE_KEY);
return Reflect.ownKeys(target);
}
const mutableHandlers = {
get,
set,
deleteProperty,
has,
ownKeys
};
const readonlyHandlers = {
get: readonlyGet,
set(target, key) {
{
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
},
deleteProperty(target, key) {
{
console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
}
};
const shallowReactiveHandlers = /*#__PURE__*/ extend({}, mutableHandlers, {
get: shallowGet,
set: shallowSet
});
// Props handlers are special in the sense that it should not unwrap top-level
// refs (in order to allow refs to be explicitly passed down), but should
// retain the reactivity of the normal readonly object.
const shallowReadonlyHandlers = /*#__PURE__*/ extend({}, readonlyHandlers, {
get: shallowReadonlyGet
});
const toReactive = (value) => isObject(value) ? reactive(value) : value;
const toReadonly = (value) => isObject(value) ? readonly(value) : value;
const toShallow = (value) => value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get$1(target, key, isReadonly = false, isShallow = false) {
// #1772: readonly(reactive(Map)) should return readonly + reactive version
// of the value
target = target["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "get" /* GET */, key);
}
!isReadonly && track(rawTarget, "get" /* GET */, rawKey);
const { has } = getProto(rawTarget);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
if (has.call(rawTarget, key)) {
return wrap(target.get(key));
}
else if (has.call(rawTarget, rawKey)) {
return wrap(target.get(rawKey));
}
else if (target !== rawTarget) {
// #3602 readonly(reactive(Map))
// ensure that the nested reactive `Map` can do tracking for itself
target.get(key);
}
}
function has$1(key, isReadonly = false) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const rawKey = toRaw(key);
if (key !== rawKey) {
!isReadonly && track(rawTarget, "has" /* HAS */, key);
}
!isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
return key === rawKey
? target.has(key)
: target.has(key) || target.has(rawKey);
}
function size(target, isReadonly = false) {
target = target["__v_raw" /* RAW */];
!isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
return Reflect.get(target, 'size', target);
}
function add(value) {
value = toRaw(value);
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, value);
if (!hadKey) {
target.add(value);
trigger(target, "add" /* ADD */, value, value);
}
return this;
}
function set$1(key, value) {
value = toRaw(value);
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else {
checkIdentityKeys(target, has, key);
}
const oldValue = get.call(target, key);
target.set(key, value);
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
return this;
}
function deleteEntry(key) {
const target = toRaw(this);
const { has, get } = getProto(target);
let hadKey = has.call(target, key);
if (!hadKey) {
key = toRaw(key);
hadKey = has.call(target, key);
}
else {
checkIdentityKeys(target, has, key);
}
const oldValue = get ? get.call(target, key) : undefined;
// forward the operation before queueing reactions
const result = target.delete(key);
if (hadKey) {
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
}
return result;
}
function clear() {
const target = toRaw(this);
const hadItems = target.size !== 0;
const oldTarget = isMap(target)
? new Map(target)
: new Set(target)
;
// forward the operation before queueing reactions
const result = target.clear();
if (hadItems) {
trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
}
return result;
}
function createForEach(isReadonly, isShallow) {
return function forEach(callback, thisArg) {
const observed = this;
const target = observed["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
return target.forEach((value, key) => {
// important: make sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
return callback.call(thisArg, wrap(value), wrap(key), observed);
});
};
}
function createIterableMethod(method, isReadonly, isShallow) {
return function (...args) {
const target = this["__v_raw" /* RAW */];
const rawTarget = toRaw(target);
const targetIsMap = isMap(rawTarget);
const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
const isKeyOnly = method === 'keys' && targetIsMap;
const innerIterator = target[method](...args);
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
!isReadonly &&
track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
// return a wrapped iterator which returns observed versions of the
// values emitted from the real iterator
return {
// iterator protocol
next() {
const { value, done } = innerIterator.next();
return done
? { value, done }
: {
value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
done
};
},
// iterable protocol
[Symbol.iterator]() {
return this;
}
};
};
}
function createReadonlyMethod(type) {
return function (...args) {
{
const key = args[0] ? `on key "${args[0]}" ` : ``;
console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
}
return type === "delete" /* DELETE */ ? false : this;
};
}
function createInstrumentations() {
const mutableInstrumentations = {
get(key) {
return get$1(this, key);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, false)
};
const shallowInstrumentations = {
get(key) {
return get$1(this, key, false, true);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false, true)
};
const readonlyInstrumentations = {
get(key) {
return get$1(this, key, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, false)
};
const shallowReadonlyInstrumentations = {
get(key) {
return get$1(this, key, true, true);
},
get size() {
return size(this, true);
},
has(key) {
return has$1.call(this, key, true);
},
add: createReadonlyMethod("add" /* ADD */),
set: createReadonlyMethod("set" /* SET */),
delete: createReadonlyMethod("delete" /* DELETE */),
clear: createReadonlyMethod("clear" /* CLEAR */),
forEach: createForEach(true, true)
};
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
iteratorMethods.forEach(method => {
mutableInstrumentations[method] = createIterableMethod(method, false, false);
readonlyInstrumentations[method] = createIterableMethod(method, true, false);
shallowInstrumentations[method] = createIterableMethod(method, false, true);
shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);
});
return [
mutableInstrumentations,
readonlyInstrumentations,
shallowInstrumentations,
shallowReadonlyInstrumentations
];
}
const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations();
function createInstrumentationGetter(isReadonly, shallow) {
const instrumentations = shallow
? isReadonly
? shallowReadonlyInstrumentations
: shallowInstrumentations
: isReadonly
? readonlyInstrumentations
: mutableInstrumentations;
return (target, key, receiver) => {
if (key === "__v_isReactive" /* IS_REACTIVE */) {
return !isReadonly;
}
else if (key === "__v_isReadonly" /* IS_READONLY */) {
return isReadonly;
}
else if (key === "__v_raw" /* RAW */) {
return target;
}
return Reflect.get(hasOwn(instrumentations, key) && key in target
? instrumentations
: target, key, receiver);
};
}
const mutableCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, false)
};
const shallowCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(false, true)
};
const readonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, false)
};
const shallowReadonlyCollectionHandlers = {
get: /*#__PURE__*/ createInstrumentationGetter(true, true)
};
function checkIdentityKeys(target, has, key) {
const rawKey = toRaw(key);
if (rawKey !== key && has.call(target, rawKey)) {
const type = toRawType(target);
console.warn(`Reactive ${type} contains both the raw and reactive ` +
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
`which can lead to inconsistencies. ` +
`Avoid differentiating between the raw and reactive versions ` +
`of an object and only use the reactive version if possible.`);
}
}
const reactiveMap = new WeakMap();
const shallowReactiveMap = new WeakMap();
const readonlyMap = new WeakMap();
const shallowReadonlyMap = new WeakMap();
function targetTypeMap(rawType) {
switch (rawType) {
case 'Object':
case 'Array':
return 1 /* COMMON */;
case 'Map':
case 'Set':
case 'WeakMap':
case 'WeakSet':
return 2 /* COLLECTION */;
default:
return 0 /* INVALID */;
}
}
function getTargetType(value) {
return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
? 0 /* INVALID */
: targetTypeMap(toRawType(value));
}
function reactive(target) {
// if trying to observe a readonly proxy, return the readonly version.
if (target && target["__v_isReadonly" /* IS_READONLY */]) {
return target;
}
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
function shallowReactive(target) {
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
function readonly(target) {
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
}
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
function shallowReadonly(target) {
return createReactiveObject(target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap);
}
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {
if (!isObject(target)) {
{
console.warn(`value cannot be made reactive: ${String(target)}`);
}
return target;
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (target["__v_raw" /* RAW */] &&
!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
return target;
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
// only a whitelist of value types can be observed.
const targetType = getTargetType(target);
if (targetType === 0 /* INVALID */) {
return target;
}
const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
proxyMap.set(target, proxy);
return proxy;
}
function isReactive(value) {
if (isReadonly(value)) {
return isReactive(value["__v_raw" /* RAW */]);
}
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
}
function isReadonly(value) {
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
}
function isProxy(value) {
return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
}
function markRaw(value) {
def(value, "__v_skip" /* SKIP */, true);
return value;
}
const convert = (val) => isObject(val) ? reactive(val) : val;
function isRef(r) {
return Boolean(r && r.__v_isRef === true);
}
function ref(value) {
return createRef(value);
}
function shallowRef(value) {
return createRef(value, true);
}
class RefImpl {
constructor(value, _shallow = false) {
this._shallow = _shallow;
this.__v_isRef = true;
this._rawValue = _shallow ? value : toRaw(value);
this._value = _shallow ? value : convert(value);
}
get value() {
track(toRaw(this), "get" /* GET */, 'value');
return this._value;
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = this._shallow ? newVal : convert(newVal);
trigger(toRaw(this), "set" /* SET */, 'value', newVal);
}
}
}
function createRef(rawValue, shallow = false) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
function triggerRef(ref) {
trigger(toRaw(ref), "set" /* SET */, 'value', ref.value );
}
function unref(ref) {
return isRef(ref) ? ref.value : ref;
}
const shallowUnwrapHandlers = {
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
set: (target, key, value, receiver) => {
const oldValue = target[key];
if (isRef(oldValue) && !isRef(value)) {
oldValue.value = value;
return true;
}
else {
return Reflect.set(target, key, value, receiver);
}
}
};
function proxyRefs(objectWithRefs) {
return isReactive(objectWithRefs)
? objectWithRefs
: new Proxy(objectWithRefs, shallowUnwrapHandlers);
}
class CustomRefImpl {
constructor(factory) {
this.__v_isRef = true;
const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
this._get = get;
this._set = set;
}
get value() {
return this._get();
}
set value(newVal) {
this._set(newVal);
}
}
function customRef(factory) {
return new CustomRefImpl(factory);
}
function toRefs(object) {
if (!isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`);
}
const ret = isArray(object) ? new Array(object.length) : {};
for (const key in object) {
ret[key] = toRef(object, key);
}
return ret;
}
class ObjectRefImpl {
constructor(_object, _key) {
this._object = _object;
this._key = _key;
this.__v_isRef = true;
}
get value() {
return this._object[this._key];
}
set value(newVal) {
this._object[this._key] = newVal;
}
}
function toRef(object, key) {
return isRef(object[key])
? object[key]
: new ObjectRefImpl(object, key);
}
class ComputedRefImpl {
constructor(getter, _setter, isReadonly) {
this._setter = _setter;
this._dirty = true;
this.__v_isRef = true;
this.effect = effect(getter, {
lazy: true,
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(toRaw(this), "set" /* SET */, 'value');
}
}
});
this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
}
get value() {
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
const self = toRaw(this);
if (self._dirty) {
self._value = this.effect();
self._dirty = false;
}
track(self, "get" /* GET */, 'value');
return self._value;
}
set value(newValue) {
this._setter(newValue);
}
}
function computed(getterOrOptions) {
let getter;
let setter;
if (isFunction(getterOrOptions)) {
getter = getterOrOptions;
setter = () => {
console.warn('Write operation failed: computed value is readonly');
}
;
}
else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set);
}
exports.ITERATE_KEY = ITERATE_KEY;
exports.computed = computed;
exports.customRef = customRef;
exports.effect = effect;
exports.enableTracking = enableTracking;
exports.isProxy = isProxy;
exports.isReactive = isReactive;
exports.isReadonly = isReadonly;
exports.isRef = isRef;
exports.markRaw = markRaw;
exports.pauseTracking = pauseTracking;
exports.proxyRefs = proxyRefs;
exports.reactive = reactive;
exports.readonly = readonly;
exports.ref = ref;
exports.resetTracking = resetTracking;
exports.shallowReactive = shallowReactive;
exports.shallowReadonly = shallowReadonly;
exports.shallowRef = shallowRef;
exports.stop = stop;
exports.toRaw = toRaw;
exports.toRef = toRef;
exports.toRefs = toRefs;
exports.track = track;
exports.trigger = trigger;
exports.triggerRef = triggerRef;
exports.unref = unref;
Object.defineProperty(exports, '__esModule', { value: true });
return exports;
}({}));

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/reactivity.cjs.prod.js')
} else {
module.exports = require('./dist/reactivity.cjs.js')
}

View File

@ -0,0 +1,41 @@
{
"name": "@vue/reactivity",
"version": "3.1.5",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",
"types": "dist/reactivity.d.ts",
"unpkg": "dist/reactivity.global.js",
"jsdelivr": "dist/reactivity.global.js",
"files": [
"index.js",
"dist"
],
"sideEffects": false,
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue-next.git",
"directory": "packages/reactivity"
},
"buildOptions": {
"name": "VueReactivity",
"formats": [
"esm-bundler",
"esm-browser",
"cjs",
"global"
]
},
"keywords": [
"vue"
],
"author": "Evan You",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vue-next/issues"
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/reactivity#readme",
"dependencies": {
"@vue/shared": "3.1.5"
}
}

View File

@ -0,0 +1 @@
../../../@vue+shared@3.1.5/node_modules/@vue/shared

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,3 @@
# @vue/shared
Internal utility functions and constants shared across `@vue` packages.

View File

@ -0,0 +1,568 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Make a map and return a function for checking if a key
* is in that map.
* IMPORTANT: all calls of this function must be prefixed with
* \/\*#\_\_PURE\_\_\*\/
* So that rollup can tree-shake them if necessary.
*/
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
/**
* dev only flag -> name mapping
*/
const PatchFlagNames = {
[1 /* TEXT */]: `TEXT`,
[2 /* CLASS */]: `CLASS`,
[4 /* STYLE */]: `STYLE`,
[8 /* PROPS */]: `PROPS`,
[16 /* FULL_PROPS */]: `FULL_PROPS`,
[32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`,
[64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`,
[128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`,
[256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`,
[512 /* NEED_PATCH */]: `NEED_PATCH`,
[1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`,
[2048 /* DEV_ROOT_FRAGMENT */]: `DEV_ROOT_FRAGMENT`,
[-1 /* HOISTED */]: `HOISTED`,
[-2 /* BAIL */]: `BAIL`
};
/**
* Dev only
*/
const slotFlagsText = {
[1 /* STABLE */]: 'STABLE',
[2 /* DYNAMIC */]: 'DYNAMIC',
[3 /* FORWARDED */]: 'FORWARDED'
};
const GLOBALS_WHITE_LISTED = 'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt';
const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED);
const range = 2;
function generateCodeFrame(source, start = 0, end = source.length) {
// Split the content into individual lines but capture the newline sequence
// that separated each line. This is important because the actual sequence is
// needed to properly take into account the full line length for offset
// comparison
let lines = source.split(/(\r?\n)/);
// Separate the lines and newline sequences into separate arrays for easier referencing
const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);
lines = lines.filter((_, idx) => idx % 2 === 0);
let count = 0;
const res = [];
for (let i = 0; i < lines.length; i++) {
count +=
lines[i].length +
((newlineSequences[i] && newlineSequences[i].length) || 0);
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length)
continue;
const line = j + 1;
res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
const lineLength = lines[j].length;
const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0;
if (j === i) {
// push underline
const pad = start - (count - (lineLength + newLineSeqLength));
const length = Math.max(1, end > count ? lineLength - pad : end - start);
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
}
else if (j > i) {
if (end > count) {
const length = Math.max(Math.min(end - count, lineLength), 1);
res.push(` | ` + '^'.repeat(length));
}
count += lineLength + newLineSeqLength;
}
}
break;
}
}
return res.join('\n');
}
/**
* On the client we only need to offer special cases for boolean attributes that
* have different names from their corresponding dom properties:
* - itemscope -> N/A
* - allowfullscreen -> allowFullscreen
* - formnovalidate -> formNoValidate
* - ismap -> isMap
* - nomodule -> noModule
* - novalidate -> noValidate
* - readonly -> readOnly
*/
const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs);
/**
* The full list is needed during SSR to produce the correct initial markup.
*/
const isBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs +
`,async,autofocus,autoplay,controls,default,defer,disabled,hidden,` +
`loop,open,required,reversed,scoped,seamless,` +
`checked,muted,multiple,selected`);
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/;
const attrValidationCache = {};
function isSSRSafeAttrName(name) {
if (attrValidationCache.hasOwnProperty(name)) {
return attrValidationCache[name];
}
const isUnsafe = unsafeAttrCharRE.test(name);
if (isUnsafe) {
console.error(`unsafe attribute name: ${name}`);
}
return (attrValidationCache[name] = !isUnsafe);
}
const propsToAttrMap = {
acceptCharset: 'accept-charset',
className: 'class',
htmlFor: 'for',
httpEquiv: 'http-equiv'
};
/**
* CSS properties that accept plain numbers
*/
const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(`animation-iteration-count,border-image-outset,border-image-slice,` +
`border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,` +
`columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,` +
`grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,` +
`grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,` +
`line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,` +
// SVG
`fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,` +
`stroke-miterlimit,stroke-opacity,stroke-width`);
/**
* Known attributes, this is used for stringification of runtime static nodes
* so that we don't stringify bindings that cannot be set from HTML.
* Don't also forget to allow `data-*` and `aria-*`!
* Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
*/
const isKnownAttr = /*#__PURE__*/ makeMap(`accept,accept-charset,accesskey,action,align,allow,alt,async,` +
`autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` +
`border,buffered,capture,challenge,charset,checked,cite,class,code,` +
`codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` +
`coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` +
`disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` +
`formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` +
`height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,` +
`ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` +
`manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` +
`open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` +
`referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` +
`selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` +
`start,step,style,summary,tabindex,target,title,translate,type,usemap,` +
`value,width,wrap`);
function normalizeStyle(value) {
if (isArray(value)) {
const res = {};
for (let i = 0; i < value.length; i++) {
const item = value[i];
const normalized = normalizeStyle(isString(item) ? parseStringStyle(item) : item);
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key];
}
}
}
return res;
}
else if (isObject(value)) {
return value;
}
}
const listDelimiterRE = /;(?![^(]*\))/g;
const propertyDelimiterRE = /:(.+)/;
function parseStringStyle(cssText) {
const ret = {};
cssText.split(listDelimiterRE).forEach(item => {
if (item) {
const tmp = item.split(propertyDelimiterRE);
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());
}
});
return ret;
}
function stringifyStyle(styles) {
let ret = '';
if (!styles) {
return ret;
}
for (const key in styles) {
const value = styles[key];
const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key);
if (isString(value) ||
(typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))) {
// only render valid values
ret += `${normalizedKey}:${value};`;
}
}
return ret;
}
function normalizeClass(value) {
let res = '';
if (isString(value)) {
res = value;
}
else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
const normalized = normalizeClass(value[i]);
if (normalized) {
res += normalized + ' ';
}
}
}
else if (isObject(value)) {
for (const name in value) {
if (value[name]) {
res += name + ' ';
}
}
}
return res.trim();
}
// These tag configs are shared between compiler-dom and runtime-dom, so they
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
const HTML_TAGS = 'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
'header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,' +
'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
'data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,' +
'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
'option,output,progress,select,textarea,details,dialog,menu,' +
'summary,template,blockquote,iframe,tfoot';
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const VOID_TAGS = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr';
const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS);
const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS);
const isVoidTag = /*#__PURE__*/ makeMap(VOID_TAGS);
const escapeRE = /["'&<>]/;
function escapeHtml(string) {
const str = '' + string;
const match = escapeRE.exec(str);
if (!match) {
return str;
}
let html = '';
let escaped;
let index;
let lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escaped = '&quot;';
break;
case 38: // &
escaped = '&amp;';
break;
case 39: // '
escaped = '&#39;';
break;
case 60: // <
escaped = '&lt;';
break;
case 62: // >
escaped = '&gt;';
break;
default:
continue;
}
if (lastIndex !== index) {
html += str.substring(lastIndex, index);
}
lastIndex = index + 1;
html += escaped;
}
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
}
// https://www.w3.org/TR/html52/syntax.html#comments
const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g;
function escapeHtmlComment(src) {
return src.replace(commentStripRE, '');
}
function looseCompareArrays(a, b) {
if (a.length !== b.length)
return false;
let equal = true;
for (let i = 0; equal && i < a.length; i++) {
equal = looseEqual(a[i], b[i]);
}
return equal;
}
function looseEqual(a, b) {
if (a === b)
return true;
let aValidType = isDate(a);
let bValidType = isDate(b);
if (aValidType || bValidType) {
return aValidType && bValidType ? a.getTime() === b.getTime() : false;
}
aValidType = isArray(a);
bValidType = isArray(b);
if (aValidType || bValidType) {
return aValidType && bValidType ? looseCompareArrays(a, b) : false;
}
aValidType = isObject(a);
bValidType = isObject(b);
if (aValidType || bValidType) {
/* istanbul ignore if: this if will probably never be called */
if (!aValidType || !bValidType) {
return false;
}
const aKeysCount = Object.keys(a).length;
const bKeysCount = Object.keys(b).length;
if (aKeysCount !== bKeysCount) {
return false;
}
for (const key in a) {
const aHasKey = a.hasOwnProperty(key);
const bHasKey = b.hasOwnProperty(key);
if ((aHasKey && !bHasKey) ||
(!aHasKey && bHasKey) ||
!looseEqual(a[key], b[key])) {
return false;
}
}
}
return String(a) === String(b);
}
function looseIndexOf(arr, val) {
return arr.findIndex(item => looseEqual(item, val));
}
/**
* For converting {{ interpolation }} values to displayed strings.
* @private
*/
const toDisplayString = (val) => {
return val == null
? ''
: isObject(val)
? JSON.stringify(val, replacer, 2)
: String(val);
};
const replacer = (_key, val) => {
if (isMap(val)) {
return {
[`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => {
entries[`${key} =>`] = val;
return entries;
}, {})
};
}
else if (isSet(val)) {
return {
[`Set(${val.size})`]: [...val.values()]
};
}
else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {
return String(val);
}
return val;
};
/**
* List of @babel/parser plugins that are used for template expression
* transforms and SFC script transforms. By default we enable proposals slated
* for ES2020. This will need to be updated as the spec moves forward.
* Full list at https://babeljs.io/docs/en/next/babel-parser#plugins
*/
const babelParserDefaultPlugins = [
'bigInt',
'optionalChaining',
'nullishCoalescingOperator'
];
const EMPTY_OBJ = Object.freeze({})
;
const EMPTY_ARR = Object.freeze([]) ;
const NOOP = () => { };
/**
* Always return false.
*/
const NO = () => false;
const onRE = /^on[^a-z]/;
const isOn = (key) => onRE.test(key);
const isModelListener = (key) => key.startsWith('onUpdate:');
const extend = Object.assign;
const remove = (arr, el) => {
const i = arr.indexOf(el);
if (i > -1) {
arr.splice(i, 1);
}
};
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const isArray = Array.isArray;
const isMap = (val) => toTypeString(val) === '[object Map]';
const isSet = (val) => toTypeString(val) === '[object Set]';
const isDate = (val) => val instanceof Date;
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isSymbol = (val) => typeof val === 'symbol';
const isObject = (val) => val !== null && typeof val === 'object';
const isPromise = (val) => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
// extract "RawType" from strings like "[object RawType]"
return toTypeString(value).slice(8, -1);
};
const isPlainObject = (val) => toTypeString(val) === '[object Object]';
const isIntegerKey = (key) => isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key;
const isReservedProp = /*#__PURE__*/ makeMap(
// the leading comma is intentional so empty string "" is also included
',key,ref,' +
'onVnodeBeforeMount,onVnodeMounted,' +
'onVnodeBeforeUpdate,onVnodeUpdated,' +
'onVnodeBeforeUnmount,onVnodeUnmounted');
const cacheStringFunction = (fn) => {
const cache = Object.create(null);
return ((str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
});
};
const camelizeRE = /-(\w)/g;
/**
* @private
*/
const camelize = cacheStringFunction((str) => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
});
const hyphenateRE = /\B([A-Z])/g;
/**
* @private
*/
const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, '-$1').toLowerCase());
/**
* @private
*/
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
/**
* @private
*/
const toHandlerKey = cacheStringFunction((str) => (str ? `on${capitalize(str)}` : ``));
// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
const invokeArrayFns = (fns, arg) => {
for (let i = 0; i < fns.length; i++) {
fns[i](arg);
}
};
const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: false,
value
});
};
const toNumber = (val) => {
const n = parseFloat(val);
return isNaN(n) ? val : n;
};
let _globalThis;
const getGlobalThis = () => {
return (_globalThis ||
(_globalThis =
typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {}));
};
exports.EMPTY_ARR = EMPTY_ARR;
exports.EMPTY_OBJ = EMPTY_OBJ;
exports.NO = NO;
exports.NOOP = NOOP;
exports.PatchFlagNames = PatchFlagNames;
exports.babelParserDefaultPlugins = babelParserDefaultPlugins;
exports.camelize = camelize;
exports.capitalize = capitalize;
exports.def = def;
exports.escapeHtml = escapeHtml;
exports.escapeHtmlComment = escapeHtmlComment;
exports.extend = extend;
exports.generateCodeFrame = generateCodeFrame;
exports.getGlobalThis = getGlobalThis;
exports.hasChanged = hasChanged;
exports.hasOwn = hasOwn;
exports.hyphenate = hyphenate;
exports.invokeArrayFns = invokeArrayFns;
exports.isArray = isArray;
exports.isBooleanAttr = isBooleanAttr;
exports.isDate = isDate;
exports.isFunction = isFunction;
exports.isGloballyWhitelisted = isGloballyWhitelisted;
exports.isHTMLTag = isHTMLTag;
exports.isIntegerKey = isIntegerKey;
exports.isKnownAttr = isKnownAttr;
exports.isMap = isMap;
exports.isModelListener = isModelListener;
exports.isNoUnitNumericStyleProp = isNoUnitNumericStyleProp;
exports.isObject = isObject;
exports.isOn = isOn;
exports.isPlainObject = isPlainObject;
exports.isPromise = isPromise;
exports.isReservedProp = isReservedProp;
exports.isSSRSafeAttrName = isSSRSafeAttrName;
exports.isSVGTag = isSVGTag;
exports.isSet = isSet;
exports.isSpecialBooleanAttr = isSpecialBooleanAttr;
exports.isString = isString;
exports.isSymbol = isSymbol;
exports.isVoidTag = isVoidTag;
exports.looseEqual = looseEqual;
exports.looseIndexOf = looseIndexOf;
exports.makeMap = makeMap;
exports.normalizeClass = normalizeClass;
exports.normalizeStyle = normalizeStyle;
exports.objectToString = objectToString;
exports.parseStringStyle = parseStringStyle;
exports.propsToAttrMap = propsToAttrMap;
exports.remove = remove;
exports.slotFlagsText = slotFlagsText;
exports.stringifyStyle = stringifyStyle;
exports.toDisplayString = toDisplayString;
exports.toHandlerKey = toHandlerKey;
exports.toNumber = toNumber;
exports.toRawType = toRawType;
exports.toTypeString = toTypeString;

View File

@ -0,0 +1,567 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Make a map and return a function for checking if a key
* is in that map.
* IMPORTANT: all calls of this function must be prefixed with
* \/\*#\_\_PURE\_\_\*\/
* So that rollup can tree-shake them if necessary.
*/
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
/**
* dev only flag -> name mapping
*/
const PatchFlagNames = {
[1 /* TEXT */]: `TEXT`,
[2 /* CLASS */]: `CLASS`,
[4 /* STYLE */]: `STYLE`,
[8 /* PROPS */]: `PROPS`,
[16 /* FULL_PROPS */]: `FULL_PROPS`,
[32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`,
[64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`,
[128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`,
[256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`,
[512 /* NEED_PATCH */]: `NEED_PATCH`,
[1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`,
[2048 /* DEV_ROOT_FRAGMENT */]: `DEV_ROOT_FRAGMENT`,
[-1 /* HOISTED */]: `HOISTED`,
[-2 /* BAIL */]: `BAIL`
};
/**
* Dev only
*/
const slotFlagsText = {
[1 /* STABLE */]: 'STABLE',
[2 /* DYNAMIC */]: 'DYNAMIC',
[3 /* FORWARDED */]: 'FORWARDED'
};
const GLOBALS_WHITE_LISTED = 'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt';
const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED);
const range = 2;
function generateCodeFrame(source, start = 0, end = source.length) {
// Split the content into individual lines but capture the newline sequence
// that separated each line. This is important because the actual sequence is
// needed to properly take into account the full line length for offset
// comparison
let lines = source.split(/(\r?\n)/);
// Separate the lines and newline sequences into separate arrays for easier referencing
const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);
lines = lines.filter((_, idx) => idx % 2 === 0);
let count = 0;
const res = [];
for (let i = 0; i < lines.length; i++) {
count +=
lines[i].length +
((newlineSequences[i] && newlineSequences[i].length) || 0);
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length)
continue;
const line = j + 1;
res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
const lineLength = lines[j].length;
const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0;
if (j === i) {
// push underline
const pad = start - (count - (lineLength + newLineSeqLength));
const length = Math.max(1, end > count ? lineLength - pad : end - start);
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
}
else if (j > i) {
if (end > count) {
const length = Math.max(Math.min(end - count, lineLength), 1);
res.push(` | ` + '^'.repeat(length));
}
count += lineLength + newLineSeqLength;
}
}
break;
}
}
return res.join('\n');
}
/**
* On the client we only need to offer special cases for boolean attributes that
* have different names from their corresponding dom properties:
* - itemscope -> N/A
* - allowfullscreen -> allowFullscreen
* - formnovalidate -> formNoValidate
* - ismap -> isMap
* - nomodule -> noModule
* - novalidate -> noValidate
* - readonly -> readOnly
*/
const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs);
/**
* The full list is needed during SSR to produce the correct initial markup.
*/
const isBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs +
`,async,autofocus,autoplay,controls,default,defer,disabled,hidden,` +
`loop,open,required,reversed,scoped,seamless,` +
`checked,muted,multiple,selected`);
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/;
const attrValidationCache = {};
function isSSRSafeAttrName(name) {
if (attrValidationCache.hasOwnProperty(name)) {
return attrValidationCache[name];
}
const isUnsafe = unsafeAttrCharRE.test(name);
if (isUnsafe) {
console.error(`unsafe attribute name: ${name}`);
}
return (attrValidationCache[name] = !isUnsafe);
}
const propsToAttrMap = {
acceptCharset: 'accept-charset',
className: 'class',
htmlFor: 'for',
httpEquiv: 'http-equiv'
};
/**
* CSS properties that accept plain numbers
*/
const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(`animation-iteration-count,border-image-outset,border-image-slice,` +
`border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,` +
`columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,` +
`grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,` +
`grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,` +
`line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,` +
// SVG
`fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,` +
`stroke-miterlimit,stroke-opacity,stroke-width`);
/**
* Known attributes, this is used for stringification of runtime static nodes
* so that we don't stringify bindings that cannot be set from HTML.
* Don't also forget to allow `data-*` and `aria-*`!
* Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
*/
const isKnownAttr = /*#__PURE__*/ makeMap(`accept,accept-charset,accesskey,action,align,allow,alt,async,` +
`autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` +
`border,buffered,capture,challenge,charset,checked,cite,class,code,` +
`codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` +
`coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` +
`disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` +
`formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` +
`height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,` +
`ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` +
`manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` +
`open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` +
`referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` +
`selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` +
`start,step,style,summary,tabindex,target,title,translate,type,usemap,` +
`value,width,wrap`);
function normalizeStyle(value) {
if (isArray(value)) {
const res = {};
for (let i = 0; i < value.length; i++) {
const item = value[i];
const normalized = normalizeStyle(isString(item) ? parseStringStyle(item) : item);
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key];
}
}
}
return res;
}
else if (isObject(value)) {
return value;
}
}
const listDelimiterRE = /;(?![^(]*\))/g;
const propertyDelimiterRE = /:(.+)/;
function parseStringStyle(cssText) {
const ret = {};
cssText.split(listDelimiterRE).forEach(item => {
if (item) {
const tmp = item.split(propertyDelimiterRE);
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());
}
});
return ret;
}
function stringifyStyle(styles) {
let ret = '';
if (!styles) {
return ret;
}
for (const key in styles) {
const value = styles[key];
const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key);
if (isString(value) ||
(typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))) {
// only render valid values
ret += `${normalizedKey}:${value};`;
}
}
return ret;
}
function normalizeClass(value) {
let res = '';
if (isString(value)) {
res = value;
}
else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
const normalized = normalizeClass(value[i]);
if (normalized) {
res += normalized + ' ';
}
}
}
else if (isObject(value)) {
for (const name in value) {
if (value[name]) {
res += name + ' ';
}
}
}
return res.trim();
}
// These tag configs are shared between compiler-dom and runtime-dom, so they
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
const HTML_TAGS = 'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
'header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,' +
'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
'data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,' +
'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
'option,output,progress,select,textarea,details,dialog,menu,' +
'summary,template,blockquote,iframe,tfoot';
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const VOID_TAGS = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr';
const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS);
const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS);
const isVoidTag = /*#__PURE__*/ makeMap(VOID_TAGS);
const escapeRE = /["'&<>]/;
function escapeHtml(string) {
const str = '' + string;
const match = escapeRE.exec(str);
if (!match) {
return str;
}
let html = '';
let escaped;
let index;
let lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escaped = '&quot;';
break;
case 38: // &
escaped = '&amp;';
break;
case 39: // '
escaped = '&#39;';
break;
case 60: // <
escaped = '&lt;';
break;
case 62: // >
escaped = '&gt;';
break;
default:
continue;
}
if (lastIndex !== index) {
html += str.substring(lastIndex, index);
}
lastIndex = index + 1;
html += escaped;
}
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
}
// https://www.w3.org/TR/html52/syntax.html#comments
const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g;
function escapeHtmlComment(src) {
return src.replace(commentStripRE, '');
}
function looseCompareArrays(a, b) {
if (a.length !== b.length)
return false;
let equal = true;
for (let i = 0; equal && i < a.length; i++) {
equal = looseEqual(a[i], b[i]);
}
return equal;
}
function looseEqual(a, b) {
if (a === b)
return true;
let aValidType = isDate(a);
let bValidType = isDate(b);
if (aValidType || bValidType) {
return aValidType && bValidType ? a.getTime() === b.getTime() : false;
}
aValidType = isArray(a);
bValidType = isArray(b);
if (aValidType || bValidType) {
return aValidType && bValidType ? looseCompareArrays(a, b) : false;
}
aValidType = isObject(a);
bValidType = isObject(b);
if (aValidType || bValidType) {
/* istanbul ignore if: this if will probably never be called */
if (!aValidType || !bValidType) {
return false;
}
const aKeysCount = Object.keys(a).length;
const bKeysCount = Object.keys(b).length;
if (aKeysCount !== bKeysCount) {
return false;
}
for (const key in a) {
const aHasKey = a.hasOwnProperty(key);
const bHasKey = b.hasOwnProperty(key);
if ((aHasKey && !bHasKey) ||
(!aHasKey && bHasKey) ||
!looseEqual(a[key], b[key])) {
return false;
}
}
}
return String(a) === String(b);
}
function looseIndexOf(arr, val) {
return arr.findIndex(item => looseEqual(item, val));
}
/**
* For converting {{ interpolation }} values to displayed strings.
* @private
*/
const toDisplayString = (val) => {
return val == null
? ''
: isObject(val)
? JSON.stringify(val, replacer, 2)
: String(val);
};
const replacer = (_key, val) => {
if (isMap(val)) {
return {
[`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => {
entries[`${key} =>`] = val;
return entries;
}, {})
};
}
else if (isSet(val)) {
return {
[`Set(${val.size})`]: [...val.values()]
};
}
else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {
return String(val);
}
return val;
};
/**
* List of @babel/parser plugins that are used for template expression
* transforms and SFC script transforms. By default we enable proposals slated
* for ES2020. This will need to be updated as the spec moves forward.
* Full list at https://babeljs.io/docs/en/next/babel-parser#plugins
*/
const babelParserDefaultPlugins = [
'bigInt',
'optionalChaining',
'nullishCoalescingOperator'
];
const EMPTY_OBJ = {};
const EMPTY_ARR = [];
const NOOP = () => { };
/**
* Always return false.
*/
const NO = () => false;
const onRE = /^on[^a-z]/;
const isOn = (key) => onRE.test(key);
const isModelListener = (key) => key.startsWith('onUpdate:');
const extend = Object.assign;
const remove = (arr, el) => {
const i = arr.indexOf(el);
if (i > -1) {
arr.splice(i, 1);
}
};
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const isArray = Array.isArray;
const isMap = (val) => toTypeString(val) === '[object Map]';
const isSet = (val) => toTypeString(val) === '[object Set]';
const isDate = (val) => val instanceof Date;
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isSymbol = (val) => typeof val === 'symbol';
const isObject = (val) => val !== null && typeof val === 'object';
const isPromise = (val) => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
// extract "RawType" from strings like "[object RawType]"
return toTypeString(value).slice(8, -1);
};
const isPlainObject = (val) => toTypeString(val) === '[object Object]';
const isIntegerKey = (key) => isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key;
const isReservedProp = /*#__PURE__*/ makeMap(
// the leading comma is intentional so empty string "" is also included
',key,ref,' +
'onVnodeBeforeMount,onVnodeMounted,' +
'onVnodeBeforeUpdate,onVnodeUpdated,' +
'onVnodeBeforeUnmount,onVnodeUnmounted');
const cacheStringFunction = (fn) => {
const cache = Object.create(null);
return ((str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
});
};
const camelizeRE = /-(\w)/g;
/**
* @private
*/
const camelize = cacheStringFunction((str) => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
});
const hyphenateRE = /\B([A-Z])/g;
/**
* @private
*/
const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, '-$1').toLowerCase());
/**
* @private
*/
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
/**
* @private
*/
const toHandlerKey = cacheStringFunction((str) => (str ? `on${capitalize(str)}` : ``));
// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
const invokeArrayFns = (fns, arg) => {
for (let i = 0; i < fns.length; i++) {
fns[i](arg);
}
};
const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: false,
value
});
};
const toNumber = (val) => {
const n = parseFloat(val);
return isNaN(n) ? val : n;
};
let _globalThis;
const getGlobalThis = () => {
return (_globalThis ||
(_globalThis =
typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {}));
};
exports.EMPTY_ARR = EMPTY_ARR;
exports.EMPTY_OBJ = EMPTY_OBJ;
exports.NO = NO;
exports.NOOP = NOOP;
exports.PatchFlagNames = PatchFlagNames;
exports.babelParserDefaultPlugins = babelParserDefaultPlugins;
exports.camelize = camelize;
exports.capitalize = capitalize;
exports.def = def;
exports.escapeHtml = escapeHtml;
exports.escapeHtmlComment = escapeHtmlComment;
exports.extend = extend;
exports.generateCodeFrame = generateCodeFrame;
exports.getGlobalThis = getGlobalThis;
exports.hasChanged = hasChanged;
exports.hasOwn = hasOwn;
exports.hyphenate = hyphenate;
exports.invokeArrayFns = invokeArrayFns;
exports.isArray = isArray;
exports.isBooleanAttr = isBooleanAttr;
exports.isDate = isDate;
exports.isFunction = isFunction;
exports.isGloballyWhitelisted = isGloballyWhitelisted;
exports.isHTMLTag = isHTMLTag;
exports.isIntegerKey = isIntegerKey;
exports.isKnownAttr = isKnownAttr;
exports.isMap = isMap;
exports.isModelListener = isModelListener;
exports.isNoUnitNumericStyleProp = isNoUnitNumericStyleProp;
exports.isObject = isObject;
exports.isOn = isOn;
exports.isPlainObject = isPlainObject;
exports.isPromise = isPromise;
exports.isReservedProp = isReservedProp;
exports.isSSRSafeAttrName = isSSRSafeAttrName;
exports.isSVGTag = isSVGTag;
exports.isSet = isSet;
exports.isSpecialBooleanAttr = isSpecialBooleanAttr;
exports.isString = isString;
exports.isSymbol = isSymbol;
exports.isVoidTag = isVoidTag;
exports.looseEqual = looseEqual;
exports.looseIndexOf = looseIndexOf;
exports.makeMap = makeMap;
exports.normalizeClass = normalizeClass;
exports.normalizeStyle = normalizeStyle;
exports.objectToString = objectToString;
exports.parseStringStyle = parseStringStyle;
exports.propsToAttrMap = propsToAttrMap;
exports.remove = remove;
exports.slotFlagsText = slotFlagsText;
exports.stringifyStyle = stringifyStyle;
exports.toDisplayString = toDisplayString;
exports.toHandlerKey = toHandlerKey;
exports.toNumber = toNumber;
exports.toRawType = toRawType;
exports.toTypeString = toTypeString;

View File

@ -0,0 +1,325 @@
/**
* List of @babel/parser plugins that are used for template expression
* transforms and SFC script transforms. By default we enable proposals slated
* for ES2020. This will need to be updated as the spec moves forward.
* Full list at https://babeljs.io/docs/en/next/babel-parser#plugins
*/
export declare const babelParserDefaultPlugins: readonly ["bigInt", "optionalChaining", "nullishCoalescingOperator"];
/**
* @private
*/
export declare const camelize: (str: string) => string;
/**
* @private
*/
export declare const capitalize: (str: string) => string;
export declare const def: (obj: object, key: string | symbol, value: any) => void;
export declare const EMPTY_ARR: readonly never[];
export declare const EMPTY_OBJ: {
readonly [key: string]: any;
};
export declare function escapeHtml(string: unknown): string;
export declare function escapeHtmlComment(src: string): string;
export declare const extend: {
<T, U>(target: T, source: U): T & U;
<T_1, U_1, V>(target: T_1, source1: U_1, source2: V): T_1 & U_1 & V;
<T_2, U_2, V_1, W>(target: T_2, source1: U_2, source2: V_1, source3: W): T_2 & U_2 & V_1 & W;
(target: object, ...sources: any[]): any;
};
export declare function generateCodeFrame(source: string, start?: number, end?: number): string;
export declare const getGlobalThis: () => any;
export declare const hasChanged: (value: any, oldValue: any) => boolean;
export declare const hasOwn: (val: object, key: string | symbol) => key is never;
/**
* @private
*/
export declare const hyphenate: (str: string) => string;
export declare const invokeArrayFns: (fns: Function[], arg?: any) => void;
export declare const isArray: (arg: any) => arg is any[];
/**
* The full list is needed during SSR to produce the correct initial markup.
*/
export declare const isBooleanAttr: (key: string) => boolean;
export declare const isDate: (val: unknown) => val is Date;
export declare const isFunction: (val: unknown) => val is Function;
export declare const isGloballyWhitelisted: (key: string) => boolean;
export declare const isHTMLTag: (key: string) => boolean;
export declare const isIntegerKey: (key: unknown) => boolean;
/**
* Known attributes, this is used for stringification of runtime static nodes
* so that we don't stringify bindings that cannot be set from HTML.
* Don't also forget to allow `data-*` and `aria-*`!
* Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
*/
export declare const isKnownAttr: (key: string) => boolean;
export declare const isMap: (val: unknown) => val is Map<any, any>;
export declare const isModelListener: (key: string) => boolean;
/**
* CSS properties that accept plain numbers
*/
export declare const isNoUnitNumericStyleProp: (key: string) => boolean;
export declare const isObject: (val: unknown) => val is Record<any, any>;
export declare const isOn: (key: string) => boolean;
export declare const isPlainObject: (val: unknown) => val is object;
export declare const isPromise: <T = any>(val: unknown) => val is Promise<T>;
export declare const isReservedProp: (key: string) => boolean;
export declare const isSet: (val: unknown) => val is Set<any>;
export declare const isSpecialBooleanAttr: (key: string) => boolean;
export declare function isSSRSafeAttrName(name: string): boolean;
export declare const isString: (val: unknown) => val is string;
export declare const isSVGTag: (key: string) => boolean;
export declare const isSymbol: (val: unknown) => val is symbol;
export declare const isVoidTag: (key: string) => boolean;
export declare function looseEqual(a: any, b: any): boolean;
export declare function looseIndexOf(arr: any[], val: any): number;
/**
* Make a map and return a function for checking if a key
* is in that map.
* IMPORTANT: all calls of this function must be prefixed with
* \/\*#\_\_PURE\_\_\*\/
* So that rollup can tree-shake them if necessary.
*/
export declare function makeMap(str: string, expectsLowerCase?: boolean): (key: string) => boolean;
/**
* Always return false.
*/
export declare const NO: () => boolean;
export declare const NOOP: () => void;
export declare function normalizeClass(value: unknown): string;
export declare type NormalizedStyle = Record<string, string | number>;
export declare function normalizeStyle(value: unknown): NormalizedStyle | undefined;
export declare const objectToString: () => string;
export declare function parseStringStyle(cssText: string): NormalizedStyle;
/**
* dev only flag -> name mapping
*/
export declare const PatchFlagNames: {
[x: number]: string;
};
/**
* Patch flags are optimization hints generated by the compiler.
* when a block with dynamicChildren is encountered during diff, the algorithm
* enters "optimized mode". In this mode, we know that the vdom is produced by
* a render function generated by the compiler, so the algorithm only needs to
* handle updates explicitly marked by these patch flags.
*
* Patch flags can be combined using the | bitwise operator and can be checked
* using the & operator, e.g.
*
* ```js
* const flag = TEXT | CLASS
* if (flag & TEXT) { ... }
* ```
*
* Check the `patchElement` function in '../../runtime-core/src/renderer.ts' to see how the
* flags are handled during diff.
*/
export declare const enum PatchFlags {
/**
* Indicates an element with dynamic textContent (children fast path)
*/
TEXT = 1,
/**
* Indicates an element with dynamic class binding.
*/
CLASS = 2,
/**
* Indicates an element with dynamic style
* The compiler pre-compiles static string styles into static objects
* + detects and hoists inline static objects
* e.g. style="color: red" and :style="{ color: 'red' }" both get hoisted as
* const style = { color: 'red' }
* render() { return e('div', { style }) }
*/
STYLE = 4,
/**
* Indicates an element that has non-class/style dynamic props.
* Can also be on a component that has any dynamic props (includes
* class/style). when this flag is present, the vnode also has a dynamicProps
* array that contains the keys of the props that may change so the runtime
* can diff them faster (without having to worry about removed props)
*/
PROPS = 8,
/**
* Indicates an element with props with dynamic keys. When keys change, a full
* diff is always needed to remove the old key. This flag is mutually
* exclusive with CLASS, STYLE and PROPS.
*/
FULL_PROPS = 16,
/**
* Indicates an element with event listeners (which need to be attached
* during hydration)
*/
HYDRATE_EVENTS = 32,
/**
* Indicates a fragment whose children order doesn't change.
*/
STABLE_FRAGMENT = 64,
/**
* Indicates a fragment with keyed or partially keyed children
*/
KEYED_FRAGMENT = 128,
/**
* Indicates a fragment with unkeyed children.
*/
UNKEYED_FRAGMENT = 256,
/**
* Indicates an element that only needs non-props patching, e.g. ref or
* directives (onVnodeXXX hooks). since every patched vnode checks for refs
* and onVnodeXXX hooks, it simply marks the vnode so that a parent block
* will track it.
*/
NEED_PATCH = 512,
/**
* Indicates a component with dynamic slots (e.g. slot that references a v-for
* iterated value, or dynamic slot names).
* Components with this flag are always force updated.
*/
DYNAMIC_SLOTS = 1024,
/**
* Indicates a fragment that was created only because the user has placed
* comments at the root level of a template. This is a dev-only flag since
* comments are stripped in production.
*/
DEV_ROOT_FRAGMENT = 2048,
/**
* SPECIAL FLAGS -------------------------------------------------------------
* Special flags are negative integers. They are never matched against using
* bitwise operators (bitwise matching should only happen in branches where
* patchFlag > 0), and are mutually exclusive. When checking for a special
* flag, simply check patchFlag === FLAG.
*/
/**
* Indicates a hoisted static vnode. This is a hint for hydration to skip
* the entire sub tree since static content never needs to be updated.
*/
HOISTED = -1,
/**
* A special flag that indicates that the diffing algorithm should bail out
* of optimized mode. For example, on block fragments created by renderSlot()
* when encountering non-compiler generated slots (i.e. manually written
* render functions, which should always be fully diffed)
* OR manually cloneVNodes
*/
BAIL = -2
}
export declare const propsToAttrMap: Record<string, string | undefined>;
export declare const remove: <T>(arr: T[], el: T) => void;
export declare const enum ShapeFlags {
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 2,
STATEFUL_COMPONENT = 4,
TEXT_CHILDREN = 8,
ARRAY_CHILDREN = 16,
SLOTS_CHILDREN = 32,
TELEPORT = 64,
SUSPENSE = 128,
COMPONENT_SHOULD_KEEP_ALIVE = 256,
COMPONENT_KEPT_ALIVE = 512,
COMPONENT = 6
}
export declare const enum SlotFlags {
/**
* Stable slots that only reference slot props or context state. The slot
* can fully capture its own dependencies so when passed down the parent won't
* need to force the child to update.
*/
STABLE = 1,
/**
* Slots that reference scope variables (v-for or an outer slot prop), or
* has conditional structure (v-if, v-for). The parent will need to force
* the child to update because the slot does not fully capture its dependencies.
*/
DYNAMIC = 2,
/**
* `<slot/>` being forwarded into a child component. Whether the parent needs
* to update the child is dependent on what kind of slots the parent itself
* received. This has to be refined at runtime, when the child's vnode
* is being created (in `normalizeChildren`)
*/
FORWARDED = 3
}
/**
* Dev only
*/
export declare const slotFlagsText: {
1: string;
2: string;
3: string;
};
export declare function stringifyStyle(styles: NormalizedStyle | undefined): string;
/**
* For converting {{ interpolation }} values to displayed strings.
* @private
*/
export declare const toDisplayString: (val: unknown) => string;
/**
* @private
*/
export declare const toHandlerKey: (str: string) => string;
export declare const toNumber: (val: any) => any;
export declare const toRawType: (value: unknown) => string;
export declare const toTypeString: (value: unknown) => string;
export { }

View File

@ -0,0 +1,509 @@
/**
* Make a map and return a function for checking if a key
* is in that map.
* IMPORTANT: all calls of this function must be prefixed with
* \/\*#\_\_PURE\_\_\*\/
* So that rollup can tree-shake them if necessary.
*/
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
/**
* dev only flag -> name mapping
*/
const PatchFlagNames = {
[1 /* TEXT */]: `TEXT`,
[2 /* CLASS */]: `CLASS`,
[4 /* STYLE */]: `STYLE`,
[8 /* PROPS */]: `PROPS`,
[16 /* FULL_PROPS */]: `FULL_PROPS`,
[32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`,
[64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`,
[128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`,
[256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`,
[512 /* NEED_PATCH */]: `NEED_PATCH`,
[1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`,
[2048 /* DEV_ROOT_FRAGMENT */]: `DEV_ROOT_FRAGMENT`,
[-1 /* HOISTED */]: `HOISTED`,
[-2 /* BAIL */]: `BAIL`
};
/**
* Dev only
*/
const slotFlagsText = {
[1 /* STABLE */]: 'STABLE',
[2 /* DYNAMIC */]: 'DYNAMIC',
[3 /* FORWARDED */]: 'FORWARDED'
};
const GLOBALS_WHITE_LISTED = 'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt';
const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED);
const range = 2;
function generateCodeFrame(source, start = 0, end = source.length) {
// Split the content into individual lines but capture the newline sequence
// that separated each line. This is important because the actual sequence is
// needed to properly take into account the full line length for offset
// comparison
let lines = source.split(/(\r?\n)/);
// Separate the lines and newline sequences into separate arrays for easier referencing
const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);
lines = lines.filter((_, idx) => idx % 2 === 0);
let count = 0;
const res = [];
for (let i = 0; i < lines.length; i++) {
count +=
lines[i].length +
((newlineSequences[i] && newlineSequences[i].length) || 0);
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length)
continue;
const line = j + 1;
res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
const lineLength = lines[j].length;
const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0;
if (j === i) {
// push underline
const pad = start - (count - (lineLength + newLineSeqLength));
const length = Math.max(1, end > count ? lineLength - pad : end - start);
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
}
else if (j > i) {
if (end > count) {
const length = Math.max(Math.min(end - count, lineLength), 1);
res.push(` | ` + '^'.repeat(length));
}
count += lineLength + newLineSeqLength;
}
}
break;
}
}
return res.join('\n');
}
/**
* On the client we only need to offer special cases for boolean attributes that
* have different names from their corresponding dom properties:
* - itemscope -> N/A
* - allowfullscreen -> allowFullscreen
* - formnovalidate -> formNoValidate
* - ismap -> isMap
* - nomodule -> noModule
* - novalidate -> noValidate
* - readonly -> readOnly
*/
const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs);
/**
* The full list is needed during SSR to produce the correct initial markup.
*/
const isBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs +
`,async,autofocus,autoplay,controls,default,defer,disabled,hidden,` +
`loop,open,required,reversed,scoped,seamless,` +
`checked,muted,multiple,selected`);
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/;
const attrValidationCache = {};
function isSSRSafeAttrName(name) {
if (attrValidationCache.hasOwnProperty(name)) {
return attrValidationCache[name];
}
const isUnsafe = unsafeAttrCharRE.test(name);
if (isUnsafe) {
console.error(`unsafe attribute name: ${name}`);
}
return (attrValidationCache[name] = !isUnsafe);
}
const propsToAttrMap = {
acceptCharset: 'accept-charset',
className: 'class',
htmlFor: 'for',
httpEquiv: 'http-equiv'
};
/**
* CSS properties that accept plain numbers
*/
const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(`animation-iteration-count,border-image-outset,border-image-slice,` +
`border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,` +
`columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,` +
`grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,` +
`grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,` +
`line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,` +
// SVG
`fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,` +
`stroke-miterlimit,stroke-opacity,stroke-width`);
/**
* Known attributes, this is used for stringification of runtime static nodes
* so that we don't stringify bindings that cannot be set from HTML.
* Don't also forget to allow `data-*` and `aria-*`!
* Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
*/
const isKnownAttr = /*#__PURE__*/ makeMap(`accept,accept-charset,accesskey,action,align,allow,alt,async,` +
`autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` +
`border,buffered,capture,challenge,charset,checked,cite,class,code,` +
`codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` +
`coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` +
`disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` +
`formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` +
`height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,` +
`ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` +
`manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` +
`open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` +
`referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` +
`selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` +
`start,step,style,summary,tabindex,target,title,translate,type,usemap,` +
`value,width,wrap`);
function normalizeStyle(value) {
if (isArray(value)) {
const res = {};
for (let i = 0; i < value.length; i++) {
const item = value[i];
const normalized = normalizeStyle(isString(item) ? parseStringStyle(item) : item);
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key];
}
}
}
return res;
}
else if (isObject(value)) {
return value;
}
}
const listDelimiterRE = /;(?![^(]*\))/g;
const propertyDelimiterRE = /:(.+)/;
function parseStringStyle(cssText) {
const ret = {};
cssText.split(listDelimiterRE).forEach(item => {
if (item) {
const tmp = item.split(propertyDelimiterRE);
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());
}
});
return ret;
}
function stringifyStyle(styles) {
let ret = '';
if (!styles) {
return ret;
}
for (const key in styles) {
const value = styles[key];
const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key);
if (isString(value) ||
(typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))) {
// only render valid values
ret += `${normalizedKey}:${value};`;
}
}
return ret;
}
function normalizeClass(value) {
let res = '';
if (isString(value)) {
res = value;
}
else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
const normalized = normalizeClass(value[i]);
if (normalized) {
res += normalized + ' ';
}
}
}
else if (isObject(value)) {
for (const name in value) {
if (value[name]) {
res += name + ' ';
}
}
}
return res.trim();
}
// These tag configs are shared between compiler-dom and runtime-dom, so they
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
const HTML_TAGS = 'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
'header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,' +
'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
'data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,' +
'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
'option,output,progress,select,textarea,details,dialog,menu,' +
'summary,template,blockquote,iframe,tfoot';
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const VOID_TAGS = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr';
const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS);
const isSVGTag = /*#__PURE__*/ makeMap(SVG_TAGS);
const isVoidTag = /*#__PURE__*/ makeMap(VOID_TAGS);
const escapeRE = /["'&<>]/;
function escapeHtml(string) {
const str = '' + string;
const match = escapeRE.exec(str);
if (!match) {
return str;
}
let html = '';
let escaped;
let index;
let lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escaped = '&quot;';
break;
case 38: // &
escaped = '&amp;';
break;
case 39: // '
escaped = '&#39;';
break;
case 60: // <
escaped = '&lt;';
break;
case 62: // >
escaped = '&gt;';
break;
default:
continue;
}
if (lastIndex !== index) {
html += str.substring(lastIndex, index);
}
lastIndex = index + 1;
html += escaped;
}
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
}
// https://www.w3.org/TR/html52/syntax.html#comments
const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g;
function escapeHtmlComment(src) {
return src.replace(commentStripRE, '');
}
function looseCompareArrays(a, b) {
if (a.length !== b.length)
return false;
let equal = true;
for (let i = 0; equal && i < a.length; i++) {
equal = looseEqual(a[i], b[i]);
}
return equal;
}
function looseEqual(a, b) {
if (a === b)
return true;
let aValidType = isDate(a);
let bValidType = isDate(b);
if (aValidType || bValidType) {
return aValidType && bValidType ? a.getTime() === b.getTime() : false;
}
aValidType = isArray(a);
bValidType = isArray(b);
if (aValidType || bValidType) {
return aValidType && bValidType ? looseCompareArrays(a, b) : false;
}
aValidType = isObject(a);
bValidType = isObject(b);
if (aValidType || bValidType) {
/* istanbul ignore if: this if will probably never be called */
if (!aValidType || !bValidType) {
return false;
}
const aKeysCount = Object.keys(a).length;
const bKeysCount = Object.keys(b).length;
if (aKeysCount !== bKeysCount) {
return false;
}
for (const key in a) {
const aHasKey = a.hasOwnProperty(key);
const bHasKey = b.hasOwnProperty(key);
if ((aHasKey && !bHasKey) ||
(!aHasKey && bHasKey) ||
!looseEqual(a[key], b[key])) {
return false;
}
}
}
return String(a) === String(b);
}
function looseIndexOf(arr, val) {
return arr.findIndex(item => looseEqual(item, val));
}
/**
* For converting {{ interpolation }} values to displayed strings.
* @private
*/
const toDisplayString = (val) => {
return val == null
? ''
: isObject(val)
? JSON.stringify(val, replacer, 2)
: String(val);
};
const replacer = (_key, val) => {
if (isMap(val)) {
return {
[`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => {
entries[`${key} =>`] = val;
return entries;
}, {})
};
}
else if (isSet(val)) {
return {
[`Set(${val.size})`]: [...val.values()]
};
}
else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {
return String(val);
}
return val;
};
/**
* List of @babel/parser plugins that are used for template expression
* transforms and SFC script transforms. By default we enable proposals slated
* for ES2020. This will need to be updated as the spec moves forward.
* Full list at https://babeljs.io/docs/en/next/babel-parser#plugins
*/
const babelParserDefaultPlugins = [
'bigInt',
'optionalChaining',
'nullishCoalescingOperator'
];
const EMPTY_OBJ = (process.env.NODE_ENV !== 'production')
? Object.freeze({})
: {};
const EMPTY_ARR = (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : [];
const NOOP = () => { };
/**
* Always return false.
*/
const NO = () => false;
const onRE = /^on[^a-z]/;
const isOn = (key) => onRE.test(key);
const isModelListener = (key) => key.startsWith('onUpdate:');
const extend = Object.assign;
const remove = (arr, el) => {
const i = arr.indexOf(el);
if (i > -1) {
arr.splice(i, 1);
}
};
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const isArray = Array.isArray;
const isMap = (val) => toTypeString(val) === '[object Map]';
const isSet = (val) => toTypeString(val) === '[object Set]';
const isDate = (val) => val instanceof Date;
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isSymbol = (val) => typeof val === 'symbol';
const isObject = (val) => val !== null && typeof val === 'object';
const isPromise = (val) => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
// extract "RawType" from strings like "[object RawType]"
return toTypeString(value).slice(8, -1);
};
const isPlainObject = (val) => toTypeString(val) === '[object Object]';
const isIntegerKey = (key) => isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key;
const isReservedProp = /*#__PURE__*/ makeMap(
// the leading comma is intentional so empty string "" is also included
',key,ref,' +
'onVnodeBeforeMount,onVnodeMounted,' +
'onVnodeBeforeUpdate,onVnodeUpdated,' +
'onVnodeBeforeUnmount,onVnodeUnmounted');
const cacheStringFunction = (fn) => {
const cache = Object.create(null);
return ((str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
});
};
const camelizeRE = /-(\w)/g;
/**
* @private
*/
const camelize = cacheStringFunction((str) => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
});
const hyphenateRE = /\B([A-Z])/g;
/**
* @private
*/
const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, '-$1').toLowerCase());
/**
* @private
*/
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
/**
* @private
*/
const toHandlerKey = cacheStringFunction((str) => (str ? `on${capitalize(str)}` : ``));
// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
const invokeArrayFns = (fns, arg) => {
for (let i = 0; i < fns.length; i++) {
fns[i](arg);
}
};
const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: false,
value
});
};
const toNumber = (val) => {
const n = parseFloat(val);
return isNaN(n) ? val : n;
};
let _globalThis;
const getGlobalThis = () => {
return (_globalThis ||
(_globalThis =
typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {}));
};
export { EMPTY_ARR, EMPTY_OBJ, NO, NOOP, PatchFlagNames, babelParserDefaultPlugins, camelize, capitalize, def, escapeHtml, escapeHtmlComment, extend, generateCodeFrame, getGlobalThis, hasChanged, hasOwn, hyphenate, invokeArrayFns, isArray, isBooleanAttr, isDate, isFunction, isGloballyWhitelisted, isHTMLTag, isIntegerKey, isKnownAttr, isMap, isModelListener, isNoUnitNumericStyleProp, isObject, isOn, isPlainObject, isPromise, isReservedProp, isSSRSafeAttrName, isSVGTag, isSet, isSpecialBooleanAttr, isString, isSymbol, isVoidTag, looseEqual, looseIndexOf, makeMap, normalizeClass, normalizeStyle, objectToString, parseStringStyle, propsToAttrMap, remove, slotFlagsText, stringifyStyle, toDisplayString, toHandlerKey, toNumber, toRawType, toTypeString };

View File

@ -0,0 +1,7 @@
'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/shared.cjs.prod.js')
} else {
module.exports = require('./dist/shared.cjs.js')
}

View File

@ -0,0 +1,32 @@
{
"name": "@vue/shared",
"version": "3.1.5",
"description": "internal utils shared across @vue packages",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
"types": "dist/shared.d.ts",
"files": [
"index.js",
"dist"
],
"buildOptions": {
"formats": [
"esm-bundler",
"cjs"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue-next.git",
"directory": "packages/shared"
},
"keywords": [
"vue"
],
"author": "Evan You",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vue-next/issues"
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/shared#readme"
}

View File

@ -0,0 +1 @@
../../../@vue+reactivity@3.1.5/node_modules/@vue/reactivity

View File

@ -0,0 +1,7 @@
import Alpine from './../src/index'
window.Alpine = Alpine
queueMicrotask(() => {
Alpine.start()
})

View File

@ -0,0 +1,5 @@
import Alpine from './../src/index'
export default Alpine
export { Alpine }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
{
"name": "alpinejs",
"version": "3.14.9",
"description": "The rugged, minimal JavaScript framework",
"homepage": "https://alpinejs.dev",
"repository": {
"type": "git",
"url": "https://github.com/alpinejs/alpine.git",
"directory": "packages/alpinejs"
},
"author": "Caleb Porzio",
"license": "MIT",
"main": "dist/module.cjs.js",
"module": "dist/module.esm.js",
"unpkg": "dist/cdn.min.js",
"dependencies": {
"@vue/reactivity": "~3.1.1"
}
}

View File

@ -0,0 +1,82 @@
import { setReactivityEngine, disableEffectScheduling, reactive, effect, release, raw, watch } from './reactivity'
import { mapAttributes, directive, setPrefix as prefix, prefix as prefixed } from './directives'
import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, destroyTree, interceptInit } from './lifecycle'
import { onElRemoved, onAttributeRemoved, onAttributesAdded, mutateDom, deferMutations, flushAndStopDeferringMutations, startObservingMutations, stopObservingMutations } from './mutation'
import { mergeProxies, closestDataStack, addScopeToNode, scope as $data } from './scope'
import { setEvaluator, evaluate, evaluateLater, dontAutoEvaluateFunctions } from './evaluator'
import { transition } from './directives/x-transition'
import { clone, cloneNode, skipDuringClone, onlyDuringClone, interceptClone } from './clone'
import { interceptor } from './interceptor'
import { getBinding as bound, extractProp } from './utils/bind'
import { debounce } from './utils/debounce'
import { throttle } from './utils/throttle'
import { setStyles } from './utils/styles'
import { entangle } from './entangle'
import { nextTick } from './nextTick'
import { walk } from './utils/walk'
import { plugin } from './plugin'
import { magic } from './magics'
import { store } from './store'
import { bind } from './binds'
import { data } from './datas'
let Alpine = {
get reactive() { return reactive },
get release() { return release },
get effect() { return effect },
get raw() { return raw },
version: ALPINE_VERSION,
flushAndStopDeferringMutations,
dontAutoEvaluateFunctions,
disableEffectScheduling,
startObservingMutations,
stopObservingMutations,
setReactivityEngine,
onAttributeRemoved,
onAttributesAdded,
closestDataStack,
skipDuringClone,
onlyDuringClone,
addRootSelector,
addInitSelector,
interceptClone,
addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
interceptInit,
setEvaluator,
mergeProxies,
extractProp,
findClosest,
onElRemoved,
closestRoot,
destroyTree,
interceptor, // INTERNAL: not public API and is subject to change without major release.
transition, // INTERNAL
setStyles, // INTERNAL
mutateDom,
directive,
entangle,
throttle,
debounce,
evaluate,
initTree,
nextTick,
prefixed,
prefix,
plugin,
magic,
store,
start,
clone, // INTERNAL
cloneNode, // INTERNAL
bound,
$data,
watch,
walk,
data,
bind,
}
export default Alpine

View File

@ -0,0 +1,67 @@
import { attributesOnly, directives } from "./directives"
let binds = {}
export function bind(name, bindings) {
let getBindings = typeof bindings !== 'function' ? () => bindings : bindings
if (name instanceof Element) {
return applyBindingsObject(name, getBindings())
} else {
binds[name] = getBindings
}
return () => {} // Null cleanup...
}
export function injectBindingProviders(obj) {
Object.entries(binds).forEach(([name, callback]) => {
Object.defineProperty(obj, name, {
get() {
return (...args) => {
return callback(...args)
}
}
})
})
return obj
}
export function addVirtualBindings(el, bindings) {
let getBindings = typeof bindings !== 'function' ? () => bindings : bindings
el._x_virtualDirectives = getBindings()
}
export function applyBindingsObject(el, obj, original) {
let cleanupRunners = []
while (cleanupRunners.length) cleanupRunners.pop()()
let attributes = Object.entries(obj).map(([name, value]) => ({ name, value }))
let staticAttributes = attributesOnly(attributes)
// Handle binding normal HTML attributes (non-Alpine directives).
attributes = attributes.map(attribute => {
if (staticAttributes.find(attr => attr.name === attribute.name)) {
return {
name: `x-bind:${attribute.name}`,
value: `"${attribute.value}"`,
}
}
return attribute
})
directives(el, attributes, original).map(handle => {
cleanupRunners.push(handle.runCleanups)
handle()
})
return () => {
while (cleanupRunners.length) cleanupRunners.pop()()
}
}

View File

@ -0,0 +1,89 @@
import { effect, release, overrideEffect } from "./reactivity"
import { initTree, isRoot } from "./lifecycle"
import { walk } from "./utils/walk"
export let isCloning = false
export function skipDuringClone(callback, fallback = () => {}) {
return (...args) => isCloning ? fallback(...args) : callback(...args)
}
export function onlyDuringClone(callback) {
return (...args) => isCloning && callback(...args)
}
let interceptors = []
export function interceptClone(callback) {
interceptors.push(callback)
}
export function cloneNode(from, to)
{
interceptors.forEach(i => i(from, to))
isCloning = true
// We don't need reactive effects in the new tree.
// Cloning is just used to seed new server HTML with
// Alpine before "morphing" it onto live Alpine...
dontRegisterReactiveSideEffects(() => {
initTree(to, (el, callback) => {
// We're hijacking the "walker" so that we
// only initialize the element we're cloning...
callback(el, () => {})
})
})
isCloning = false
}
export let isCloningLegacy = false
/** deprecated */
export function clone(oldEl, newEl) {
if (! newEl._x_dataStack) newEl._x_dataStack = oldEl._x_dataStack
isCloning = true
isCloningLegacy = true
dontRegisterReactiveSideEffects(() => {
cloneTree(newEl)
})
isCloning = false
isCloningLegacy = false
}
/** deprecated */
export function cloneTree(el) {
let hasRunThroughFirstEl = false
let shallowWalker = (el, callback) => {
walk(el, (el, skip) => {
if (hasRunThroughFirstEl && isRoot(el)) return skip()
hasRunThroughFirstEl = true
callback(el, skip)
})
}
initTree(el, shallowWalker)
}
function dontRegisterReactiveSideEffects(callback) {
let cache = effect
overrideEffect((callback, el) => {
let storedEffect = cache(callback)
release(storedEffect)
return () => {}
})
callback()
overrideEffect(cache)
}

View File

@ -0,0 +1,22 @@
let datas = {}
export function data(name, callback) {
datas[name] = callback
}
export function injectDataProviders(obj, context) {
Object.entries(datas).forEach(([name, callback]) => {
Object.defineProperty(obj, name, {
get() {
return (...args) => {
return callback.bind(context)(...args)
}
},
enumerable: false,
})
})
return obj
}

View File

@ -0,0 +1,225 @@
import { onAttributeRemoved, onElRemoved } from './mutation'
import { evaluate, evaluateLater } from './evaluator'
import { elementBoundEffect } from './reactivity'
import Alpine from './alpine'
let prefixAsString = 'x-'
export function prefix(subject = '') {
return prefixAsString + subject
}
export function setPrefix(newPrefix) {
prefixAsString = newPrefix
}
let directiveHandlers = {}
export function directive(name, callback) {
directiveHandlers[name] = callback
return {
before(directive) {
if (!directiveHandlers[directive]) {
console.warn(String.raw`Cannot find directive \`${directive}\`. \`${name}\` will use the default order of execution`);
return;
}
const pos = directiveOrder.indexOf(directive);
directiveOrder.splice(pos >= 0 ? pos : directiveOrder.indexOf('DEFAULT'), 0, name);
}
}
}
export function directiveExists(name) {
return Object.keys(directiveHandlers).includes(name)
}
export function directives(el, attributes, originalAttributeOverride) {
attributes = Array.from(attributes)
if (el._x_virtualDirectives) {
let vAttributes = Object.entries(el._x_virtualDirectives).map(([name, value]) => ({ name, value }))
let staticAttributes = attributesOnly(vAttributes)
// Handle binding normal HTML attributes (non-Alpine directives).
vAttributes = vAttributes.map(attribute => {
if (staticAttributes.find(attr => attr.name === attribute.name)) {
return {
name: `x-bind:${attribute.name}`,
value: `"${attribute.value}"`,
}
}
return attribute
})
attributes = attributes.concat(vAttributes)
}
let transformedAttributeMap = {}
let directives = attributes
.map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName))
.filter(outNonAlpineAttributes)
.map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride))
.sort(byPriority)
return directives.map(directive => {
return getDirectiveHandler(el, directive)
})
}
export function attributesOnly(attributes) {
return Array.from(attributes)
.map(toTransformedAttributes())
.filter(attr => ! outNonAlpineAttributes(attr))
}
let isDeferringHandlers = false
let directiveHandlerStacks = new Map
let currentHandlerStackKey = Symbol()
export function deferHandlingDirectives(callback) {
isDeferringHandlers = true
let key = Symbol()
currentHandlerStackKey = key
directiveHandlerStacks.set(key, [])
let flushHandlers = () => {
while (directiveHandlerStacks.get(key).length) directiveHandlerStacks.get(key).shift()()
directiveHandlerStacks.delete(key)
}
let stopDeferring = () => { isDeferringHandlers = false; flushHandlers() }
callback(flushHandlers)
stopDeferring()
}
export function getElementBoundUtilities(el) {
let cleanups = []
let cleanup = callback => cleanups.push(callback)
let [effect, cleanupEffect] = elementBoundEffect(el)
cleanups.push(cleanupEffect)
let utilities = {
Alpine,
effect,
cleanup,
evaluateLater: evaluateLater.bind(evaluateLater, el),
evaluate: evaluate.bind(evaluate, el),
}
let doCleanup = () => cleanups.forEach(i => i())
return [utilities, doCleanup]
}
export function getDirectiveHandler(el, directive) {
let noop = () => {}
let handler = directiveHandlers[directive.type] || noop
let [utilities, cleanup] = getElementBoundUtilities(el)
onAttributeRemoved(el, directive.original, cleanup)
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf) return
handler.inline && handler.inline(el, directive, utilities)
handler = handler.bind(handler, el, directive, utilities)
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler) : handler()
}
fullHandler.runCleanups = cleanup
return fullHandler
}
export let startingWith = (subject, replacement) => ({ name, value }) => {
if (name.startsWith(subject)) name = name.replace(subject, replacement)
return { name, value }
}
export let into = i => i
function toTransformedAttributes(callback = () => {}) {
return ({ name, value }) => {
let { name: newName, value: newValue } = attributeTransformers.reduce((carry, transform) => {
return transform(carry)
}, { name, value })
if (newName !== name) callback(newName, name)
return { name: newName, value: newValue }
}
}
let attributeTransformers = []
export function mapAttributes(callback) {
attributeTransformers.push(callback)
}
function outNonAlpineAttributes({ name }) {
return alpineAttributeRegex().test(name)
}
let alpineAttributeRegex = () => (new RegExp(`^${prefixAsString}([^:^.]+)\\b`))
function toParsedDirectives(transformedAttributeMap, originalAttributeOverride) {
return ({ name, value }) => {
let typeMatch = name.match(alpineAttributeRegex())
let valueMatch = name.match(/:([a-zA-Z0-9\-_:]+)/)
let modifiers = name.match(/\.[^.\]]+(?=[^\]]*$)/g) || []
let original = originalAttributeOverride || transformedAttributeMap[name] || name
return {
type: typeMatch ? typeMatch[1] : null,
value: valueMatch ? valueMatch[1] : null,
modifiers: modifiers.map(i => i.replace('.', '')),
expression: value,
original,
}
}
}
const DEFAULT = 'DEFAULT'
let directiveOrder = [
'ignore',
'ref',
'data',
'id',
'anchor',
'bind',
'init',
'for',
'model',
'modelable',
'transition',
'show',
'if',
DEFAULT,
'teleport',
]
function byPriority(a, b) {
let typeA = directiveOrder.indexOf(a.type) === -1 ? DEFAULT : a.type
let typeB = directiveOrder.indexOf(b.type) === -1 ? DEFAULT : b.type
return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB)
}

View File

@ -0,0 +1,31 @@
import { directive } from '../directives'
import { warn } from '../utils/warn'
import './x-transition'
import './x-modelable'
import './x-teleport'
import './x-ignore'
import './x-effect'
import './x-model'
import './x-cloak'
import './x-init'
import './x-text'
import './x-html'
import './x-bind'
import './x-data'
import './x-show'
import './x-for'
import './x-ref'
import './x-if'
import './x-id'
import './x-on'
// Register warnings for people using plugin syntaxes and not loading the plugin itself:
warnMissingPluginDirective('Collapse', 'collapse', 'collapse')
warnMissingPluginDirective('Intersect', 'intersect', 'intersect')
warnMissingPluginDirective('Focus', 'trap', 'focus')
warnMissingPluginDirective('Mask', 'mask', 'mask')
function warnMissingPluginDirective(name, directiveName, slug) {
directive(directiveName, (el) => warn(`You can't use [x-${directiveName}] without first installing the "${name}" plugin here: https://alpinejs.dev/plugins/${slug}`, el))
}

View File

@ -0,0 +1,60 @@
import { directive, into, mapAttributes, prefix, startingWith } from '../directives'
import { evaluateLater } from '../evaluator'
import { mutateDom } from '../mutation'
import bind from '../utils/bind'
import { applyBindingsObject, injectBindingProviders } from '../binds'
mapAttributes(startingWith(':', into(prefix('bind:'))))
let handler = (el, { value, modifiers, expression, original }, { effect, cleanup }) => {
if (! value) {
let bindingProviders = {}
injectBindingProviders(bindingProviders)
let getBindings = evaluateLater(el, expression)
getBindings(bindings => {
applyBindingsObject(el, bindings, original)
}, { scope: bindingProviders } )
return
}
if (value === 'key') return storeKeyForXFor(el, expression)
if (el._x_inlineBindings && el._x_inlineBindings[value] && el._x_inlineBindings[value].extract) {
return
}
let evaluate = evaluateLater(el, expression)
effect(() => evaluate(result => {
// If nested object key is undefined, set the default value to empty string.
if (result === undefined && typeof expression === 'string' && expression.match(/\./)) {
result = ''
}
mutateDom(() => bind(el, value, result, modifiers))
}))
cleanup(() => {
el._x_undoAddedClasses && el._x_undoAddedClasses()
el._x_undoAddedStyles && el._x_undoAddedStyles()
})
}
// @todo: see if I can take advantage of the object created here inside the
// non-inline handler above so we're not duplicating work twice...
handler.inline = (el, { value, modifiers, expression }) => {
if (! value) return;
if (! el._x_inlineBindings) el._x_inlineBindings = {}
el._x_inlineBindings[value] = { expression, extract: false }
}
directive('bind', handler)
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression
}

View File

@ -0,0 +1,4 @@
import { directive, prefix } from '../directives'
import { mutateDom } from '../mutation'
directive('cloak', el => queueMicrotask(() => mutateDom(() => el.removeAttribute(prefix('cloak')))))

View File

@ -0,0 +1,67 @@
import { directive, prefix } from '../directives'
import { initInterceptors } from '../interceptor'
import { injectDataProviders } from '../datas'
import { addRootSelector } from '../lifecycle'
import { interceptClone, isCloning, isCloningLegacy } from '../clone'
import { addScopeToNode } from '../scope'
import { injectMagics, magic } from '../magics'
import { reactive } from '../reactivity'
import { evaluate } from '../evaluator'
addRootSelector(() => `[${prefix('data')}]`)
directive('data', ((el, { expression }, { cleanup }) => {
if (shouldSkipRegisteringDataDuringClone(el)) return
expression = expression === '' ? '{}' : expression
let magicContext = {}
injectMagics(magicContext, el)
let dataProviderContext = {}
injectDataProviders(dataProviderContext, magicContext)
let data = evaluate(el, expression, { scope: dataProviderContext })
if (data === undefined || data === true) data = {}
injectMagics(data, el)
let reactiveData = reactive(data)
initInterceptors(reactiveData)
let undo = addScopeToNode(el, reactiveData)
reactiveData['init'] && evaluate(el, reactiveData['init'])
cleanup(() => {
reactiveData['destroy'] && evaluate(el, reactiveData['destroy'])
undo()
})
}))
interceptClone((from, to) => {
// Transfer over existing runtime Alpine state from
// the existing dom tree over to the new one...
if (from._x_dataStack) {
to._x_dataStack = from._x_dataStack
// Set a flag to signify the new tree is using
// pre-seeded state (used so x-data knows when
// and when not to initialize state)...
to.setAttribute('data-has-alpine-state', true)
}
})
// If we are cloning a tree, we only want to evaluate x-data if another
// x-data context DOESN'T exist on the component.
// The reason a data context WOULD exist is that we graft root x-data state over
// from the live tree before hydrating the clone tree.
function shouldSkipRegisteringDataDuringClone(el) {
if (! isCloning) return false
if (isCloningLegacy) return true
return el.hasAttribute('data-has-alpine-state')
}

View File

@ -0,0 +1,7 @@
import { skipDuringClone } from '../clone'
import { directive } from '../directives'
import { evaluate, evaluateLater } from '../evaluator'
directive('effect', skipDuringClone((el, { expression }, { effect }) => {
effect(evaluateLater(el, expression))
}))

View File

@ -0,0 +1,296 @@
import { addScopeToNode } from '../scope'
import { evaluateLater } from '../evaluator'
import { directive } from '../directives'
import { reactive } from '../reactivity'
import { initTree, destroyTree } from '../lifecycle'
import { mutateDom } from '../mutation'
import { warn } from '../utils/warn'
import { skipDuringClone } from '../clone'
directive('for', (el, { expression }, { effect, cleanup }) => {
let iteratorNames = parseForExpression(expression)
let evaluateItems = evaluateLater(el, iteratorNames.items)
let evaluateKey = evaluateLater(el,
// the x-bind:key expression is stored for our use instead of evaluated.
el._x_keyExpression || 'index'
)
el._x_prevKeys = []
el._x_lookup = {}
effect(() => loop(el, iteratorNames, evaluateItems, evaluateKey))
cleanup(() => {
Object.values(el._x_lookup).forEach(el =>
mutateDom(() => {
destroyTree(el)
el.remove()
}
))
delete el._x_prevKeys
delete el._x_lookup
})
})
let shouldFastRender = true
function loop(el, iteratorNames, evaluateItems, evaluateKey) {
let isObject = i => typeof i === 'object' && ! Array.isArray(i)
let templateEl = el
evaluateItems(items => {
// Prepare yourself. There's a lot going on here. Take heart,
// every bit of complexity in this function was added for
// the purpose of making Alpine fast with large datas.
// Support number literals. Ex: x-for="i in 100"
if (isNumeric(items) && items >= 0) {
items = Array.from(Array(items).keys(), i => i + 1)
}
if (items === undefined) items = []
let lookup = el._x_lookup
let prevKeys = el._x_prevKeys
let scopes = []
let keys = []
// In order to preserve DOM elements (move instead of replace)
// we need to generate all the keys for every iteration up
// front. These will be our source of truth for diffing.
if (isObject(items)) {
items = Object.entries(items).map(([key, value]) => {
let scope = getIterationScopeVariables(iteratorNames, value, key, items)
evaluateKey(value => {
if (keys.includes(value)) warn('Duplicate key on x-for', el)
keys.push(value)
}, { scope: { index: key, ...scope} })
scopes.push(scope)
})
} else {
for (let i = 0; i < items.length; i++) {
let scope = getIterationScopeVariables(iteratorNames, items[i], i, items)
evaluateKey(value => {
if (keys.includes(value)) warn('Duplicate key on x-for', el)
keys.push(value)
}, { scope: { index: i, ...scope} })
scopes.push(scope)
}
}
// Rather than making DOM manipulations inside one large loop, we'll
// instead track which mutations need to be made in the following
// arrays. After we're finished, we can batch them at the end.
let adds = []
let moves = []
let removes = []
let sames = []
// First, we track elements that will need to be removed.
for (let i = 0; i < prevKeys.length; i++) {
let key = prevKeys[i]
if (keys.indexOf(key) === -1) removes.push(key)
}
// Notice we're mutating prevKeys as we go. This makes it
// so that we can efficiently make incremental comparisons.
prevKeys = prevKeys.filter(key => ! removes.includes(key))
let lastKey = 'template'
// This is the important part of the diffing algo. Identifying
// which keys (future DOM elements) are new, which ones have
// or haven't moved (noting where they moved to / from).
for (let i = 0; i < keys.length; i++) {
let key = keys[i]
let prevIndex = prevKeys.indexOf(key)
if (prevIndex === -1) {
// New key found.
prevKeys.splice(i, 0, key)
adds.push([lastKey, i])
} else if (prevIndex !== i) {
// A key has moved.
let keyInSpot = prevKeys.splice(i, 1)[0]
let keyForSpot = prevKeys.splice(prevIndex - 1, 1)[0]
prevKeys.splice(i, 0, keyForSpot)
prevKeys.splice(prevIndex, 0, keyInSpot)
moves.push([keyInSpot, keyForSpot])
} else {
// This key hasn't moved, but we'll still keep track
// so that we can refresh it later on.
sames.push(key)
}
lastKey = key
}
// Now that we've done the diffing work, we can apply the mutations
// in batches for both separating types work and optimizing
// for browser performance.
// We'll remove all the nodes that need to be removed,
// and clean up any side effects they had.
for (let i = 0; i < removes.length; i++) {
let key = removes[i]
if (! (key in lookup)) continue
mutateDom(() => {
destroyTree(lookup[key])
lookup[key].remove()
})
delete lookup[key]
}
// Here we'll move elements around, skipping
// mutation observer triggers by using "mutateDom".
for (let i = 0; i < moves.length; i++) {
let [keyInSpot, keyForSpot] = moves[i]
let elInSpot = lookup[keyInSpot]
let elForSpot = lookup[keyForSpot]
let marker = document.createElement('div')
mutateDom(() => {
if (! elForSpot) warn(`x-for ":key" is undefined or invalid`, templateEl, keyForSpot, lookup)
elForSpot.after(marker)
elInSpot.after(elForSpot)
elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl)
marker.before(elInSpot)
elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl)
marker.remove()
})
elForSpot._x_refreshXForScope(scopes[keys.indexOf(keyForSpot)])
}
// We can now create and add new elements.
for (let i = 0; i < adds.length; i++) {
let [lastKey, index] = adds[i]
let lastEl = (lastKey === 'template') ? templateEl : lookup[lastKey]
// If the element is a x-if template evaluated to true,
// point lastEl to the if-generated node
if (lastEl._x_currentIfEl) lastEl = lastEl._x_currentIfEl
let scope = scopes[index]
let key = keys[index]
let clone = document.importNode(templateEl.content, true).firstElementChild
let reactiveScope = reactive(scope)
addScopeToNode(clone, reactiveScope, templateEl)
clone._x_refreshXForScope = (newScope) => {
Object.entries(newScope).forEach(([key, value]) => {
reactiveScope[key] = value
})
}
mutateDom(() => {
lastEl.after(clone)
// These nodes will be "inited" as morph walks the tree...
skipDuringClone(() => initTree(clone))()
})
if (typeof key === 'object') {
warn('x-for key cannot be an object, it must be a string or an integer', templateEl)
}
lookup[key] = clone
}
// If an element hasn't changed, we still want to "refresh" the
// data it depends on in case the data has changed in an
// "unobservable" way.
for (let i = 0; i < sames.length; i++) {
lookup[sames[i]]._x_refreshXForScope(scopes[keys.indexOf(sames[i])])
}
// Now we'll log the keys (and the order they're in) for comparing
// against next time.
templateEl._x_prevKeys = keys
})
}
// This was taken from VueJS 2.* core. Thanks Vue!
function parseForExpression(expression) {
let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
let stripParensRE = /^\s*\(|\)\s*$/g
let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
let inMatch = expression.match(forAliasRE)
if (! inMatch) return
let res = {}
res.items = inMatch[2].trim()
let item = inMatch[1].replace(stripParensRE, '').trim()
let iteratorMatch = item.match(forIteratorRE)
if (iteratorMatch) {
res.item = item.replace(forIteratorRE, '').trim()
res.index = iteratorMatch[1].trim()
if (iteratorMatch[2]) {
res.collection = iteratorMatch[2].trim()
}
} else {
res.item = item
}
return res
}
function getIterationScopeVariables(iteratorNames, item, index, items) {
// We must create a new object, so each iteration has a new scope
let scopeVariables = {}
// Support array destructuring ([foo, bar]).
if (/^\[.*\]$/.test(iteratorNames.item) && Array.isArray(item)) {
let names = iteratorNames.item.replace('[', '').replace(']', '').split(',').map(i => i.trim())
names.forEach((name, i) => {
scopeVariables[name] = item[i]
})
// Support object destructuring ({ foo: 'oof', bar: 'rab' }).
} else if (/^\{.*\}$/.test(iteratorNames.item) && ! Array.isArray(item) && typeof item === 'object') {
let names = iteratorNames.item.replace('{', '').replace('}', '').split(',').map(i => i.trim())
names.forEach(name => {
scopeVariables[name] = item[name]
})
} else {
scopeVariables[iteratorNames.item] = item
}
if (iteratorNames.index) scopeVariables[iteratorNames.index] = index
if (iteratorNames.collection) scopeVariables[iteratorNames.collection] = items
return scopeVariables
}
function isNumeric(subject){
return ! Array.isArray(subject) && ! isNaN(subject)
}

View File

@ -0,0 +1,19 @@
import { directive } from '../directives'
import { initTree } from '../lifecycle'
import { mutateDom } from '../mutation'
directive('html', (el, { expression }, { effect, evaluateLater }) => {
let evaluate = evaluateLater(expression)
effect(() => {
evaluate(value => {
mutateDom(() => {
el.innerHTML = value
el._x_ignoreSelf = true
initTree(el)
delete el._x_ignoreSelf
})
})
})
})

View File

@ -0,0 +1,19 @@
import { interceptClone } from "../clone"
import { directive } from "../directives"
import { setIdRoot } from '../ids'
directive('id', (el, { expression }, { evaluate }) => {
let names = evaluate(expression)
names.forEach(name => setIdRoot(el, name))
})
interceptClone((from, to) => {
// Transfer over existing ID registrations from
// the existing dom tree over to the new one
// so that there aren't ID mismatches...
if (from._x_ids) {
to._x_ids = from._x_ids
}
})

View File

@ -0,0 +1,56 @@
import { evaluateLater } from '../evaluator'
import { addScopeToNode } from '../scope'
import { directive } from '../directives'
import { initTree, destroyTree } from '../lifecycle'
import { mutateDom } from '../mutation'
import { warn } from "../utils/warn"
import { skipDuringClone } from '../clone'
directive('if', (el, { expression }, { effect, cleanup }) => {
if (el.tagName.toLowerCase() !== 'template') warn('x-if can only be used on a <template> tag', el)
let evaluate = evaluateLater(el, expression)
let show = () => {
if (el._x_currentIfEl) return el._x_currentIfEl
let clone = el.content.cloneNode(true).firstElementChild
addScopeToNode(clone, {}, el)
mutateDom(() => {
el.after(clone)
// These nodes will be "inited" as morph walks the tree...
skipDuringClone(() => initTree(clone))()
})
el._x_currentIfEl = clone
el._x_undoIf = () => {
mutateDom(() => {
destroyTree(clone)
clone.remove()
})
delete el._x_currentIfEl
}
return clone
}
let hide = () => {
if (! el._x_undoIf) return
el._x_undoIf()
delete el._x_undoIf
}
effect(() => evaluate(value => {
value ? show() : hide()
}))
cleanup(() => el._x_undoIf && el._x_undoIf())
})

View File

@ -0,0 +1,17 @@
import { directive } from "../directives"
let handler = () => {}
handler.inline = (el, { modifiers }, { cleanup }) => {
modifiers.includes('self')
? el._x_ignoreSelf = true
: el._x_ignore = true
cleanup(() => {
modifiers.includes('self')
? delete el._x_ignoreSelf
: delete el._x_ignore
})
}
directive('ignore', handler)

View File

@ -0,0 +1,13 @@
import { directive, prefix } from "../directives";
import { addInitSelector } from "../lifecycle";
import { skipDuringClone } from "../clone";
addInitSelector(() => `[${prefix('init')}]`)
directive('init', skipDuringClone((el, { expression }, { evaluate }) => {
if (typeof expression === 'string') {
return !! expression.trim() && evaluate(expression, {}, false)
}
return evaluate(expression, {}, false)
}))

View File

@ -0,0 +1,218 @@
import bind, { isCheckbox, isRadio, safeParseBoolean } from '../utils/bind'
import { evaluateLater } from '../evaluator'
import { directive } from '../directives'
import { mutateDom } from '../mutation'
import { nextTick } from '../nextTick'
import { isCloning } from '../clone'
import on from '../utils/on'
directive('model', (el, { modifiers, expression }, { effect, cleanup }) => {
let scopeTarget = el
if (modifiers.includes('parent')) {
scopeTarget = el.parentNode
}
let evaluateGet = evaluateLater(scopeTarget, expression)
let evaluateSet
if (typeof expression === 'string') {
evaluateSet = evaluateLater(scopeTarget, `${expression} = __placeholder`)
} else if (typeof expression === 'function' && typeof expression() === 'string') {
evaluateSet = evaluateLater(scopeTarget, `${expression()} = __placeholder`)
} else {
evaluateSet = () => {}
}
let getValue = () => {
let result
evaluateGet(value => result = value)
return isGetterSetter(result) ? result.get() : result
}
let setValue = value => {
let result
evaluateGet(value => result = value)
if (isGetterSetter(result)) {
result.set(value)
} else {
evaluateSet(() => {}, {
scope: { '__placeholder': value }
})
}
}
if (typeof expression === 'string' && el.type === 'radio') {
// Radio buttons only work properly when they share a name attribute.
// People might assume we take care of that for them, because
// they already set a shared "x-model" attribute.
mutateDom(() => {
if (! el.hasAttribute('name')) el.setAttribute('name', expression)
})
}
// If the element we are binding to is a select, a radio, or checkbox
// we'll listen for the change event instead of the "input" event.
var event = (el.tagName.toLowerCase() === 'select')
|| ['checkbox', 'radio'].includes(el.type)
|| modifiers.includes('lazy')
? 'change' : 'input'
// We only want to register the event listener when we're not cloning, since the
// mutation observer handles initializing the x-model directive already when
// the element is inserted into the DOM. Otherwise we register it twice.
let removeListener = isCloning ? () => {} : on(el, event, modifiers, (e) => {
setValue(getInputValue(el, modifiers, e, getValue()))
})
if (modifiers.includes('fill'))
if ([undefined, null, ''].includes(getValue())
|| (isCheckbox(el) && Array.isArray(getValue()))
|| (el.tagName.toLowerCase() === 'select' && el.multiple)) {
setValue(
getInputValue(el, modifiers, { target: el }, getValue())
);
}
// Register the listener removal callback on the element, so that
// in addition to the cleanup function, x-modelable may call it.
// Also, make this a keyed object if we decide to reintroduce
// "named modelables" some time in a future Alpine version.
if (! el._x_removeModelListeners) el._x_removeModelListeners = {}
el._x_removeModelListeners['default'] = removeListener
cleanup(() => el._x_removeModelListeners['default']())
// If the input/select/textarea element is linked to a form
// we listen for the reset event on the parent form (the event
// does not trigger on the single inputs) and update
// on nextTick so the page doesn't end up out of sync
if (el.form) {
let removeResetListener = on(el.form, 'reset', [], (e) => {
nextTick(() => el._x_model && el._x_model.set(getInputValue(el, modifiers, { target: el }, getValue())))
})
cleanup(() => removeResetListener())
}
// Allow programmatic overriding of x-model.
el._x_model = {
get() {
return getValue()
},
set(value) {
setValue(value)
},
}
el._x_forceModelUpdate = (value) => {
// If nested model key is undefined, set the default value to empty string.
if (value === undefined && typeof expression === 'string' && expression.match(/\./)) value = ''
// @todo: This is nasty
window.fromModel = true
mutateDom(() => bind(el, 'value', value))
delete window.fromModel
}
effect(() => {
// We need to make sure we're always "getting" the value up front,
// so that we don't run into a situation where because of the early
// the reactive value isn't gotten and therefore disables future reactions.
let value = getValue()
// Don't modify the value of the input if it's focused.
if (modifiers.includes('unintrusive') && document.activeElement.isSameNode(el)) return
el._x_forceModelUpdate(value)
})
})
function getInputValue(el, modifiers, event, currentValue) {
return mutateDom(() => {
// Check for event.detail due to an issue where IE11 handles other events as a CustomEvent.
// Safari autofill triggers event as CustomEvent and assigns value to target
// so we return event.target.value instead of event.detail
if (event instanceof CustomEvent && event.detail !== undefined)
return event.detail !== null && event.detail !== undefined ? event.detail : event.target.value
else if (isCheckbox(el)) {
// If the data we are binding to is an array, toggle its value inside the array.
if (Array.isArray(currentValue)) {
let newValue = null;
if (modifiers.includes('number')) {
newValue = safeParseNumber(event.target.value)
} else if (modifiers.includes('boolean')) {
newValue = safeParseBoolean(event.target.value)
} else {
newValue = event.target.value
}
return event.target.checked
? (currentValue.includes(newValue) ? currentValue : currentValue.concat([newValue]))
: currentValue.filter(el => ! checkedAttrLooseCompare(el, newValue));
} else {
return event.target.checked
}
} else if (el.tagName.toLowerCase() === 'select' && el.multiple) {
if (modifiers.includes('number')) {
return Array.from(event.target.selectedOptions).map(option => {
let rawValue = option.value || option.text
return safeParseNumber(rawValue)
})
} else if (modifiers.includes('boolean')) {
return Array.from(event.target.selectedOptions).map(option => {
let rawValue = option.value || option.text
return safeParseBoolean(rawValue)
})
}
return Array.from(event.target.selectedOptions).map(option => {
return option.value || option.text
})
} else {
let newValue
if (isRadio(el)) {
if (event.target.checked) {
newValue = event.target.value
} else {
newValue = currentValue
}
} else {
newValue = event.target.value
}
if (modifiers.includes('number')) {
return safeParseNumber(newValue)
} else if (modifiers.includes('boolean')) {
return safeParseBoolean(newValue)
} else if (modifiers.includes('trim')) {
return newValue.trim()
} else {
return newValue
}
}
})
}
function safeParseNumber(rawValue) {
let number = rawValue ? parseFloat(rawValue) : null
return isNumeric(number) ? number : rawValue
}
function checkedAttrLooseCompare(valueA, valueB) {
return valueA == valueB
}
function isNumeric(subject){
return ! Array.isArray(subject) && ! isNaN(subject)
}
function isGetterSetter(value) {
return value !== null && typeof value === 'object' && typeof value.get === 'function' && typeof value.set === 'function'
}

View File

@ -0,0 +1,39 @@
import { directive } from '../directives'
import { entangle } from '../entangle';
directive('modelable', (el, { expression }, { effect, evaluateLater, cleanup }) => {
let func = evaluateLater(expression)
let innerGet = () => { let result; func(i => result = i); return result; }
let evaluateInnerSet = evaluateLater(`${expression} = __placeholder`)
let innerSet = val => evaluateInnerSet(() => {}, { scope: { '__placeholder': val }})
let initialValue = innerGet()
innerSet(initialValue)
queueMicrotask(() => {
if (! el._x_model) return
// Remove native event listeners as these are now bound with x-modelable.
// The reason for this is that it's often useful to wrap <input> elements
// in x-modelable/model, but the input events from the native input
// override any functionality added by x-modelable causing confusion.
el._x_removeModelListeners['default']()
let outerGet = el._x_model.get
let outerSet = el._x_model.set
let releaseEntanglement = entangle(
{
get() { return outerGet() },
set(value) { outerSet(value) },
},
{
get() { return innerGet() },
set(value) { innerSet(value) },
},
)
cleanup(releaseEntanglement)
})
})

View File

@ -0,0 +1,22 @@
import { directive, into, mapAttributes, prefix, startingWith } from '../directives'
import { evaluateLater } from '../evaluator'
import { skipDuringClone } from '../clone'
import on from '../utils/on'
mapAttributes(startingWith('@', into(prefix('on:'))))
directive('on', skipDuringClone((el, { value, modifiers, expression }, { cleanup }) => {
let evaluate = expression ? evaluateLater(el, expression) : () => {}
// Forward event listeners on portals.
if (el.tagName.toLowerCase() === 'template') {
if (! el._x_forwardEvents) el._x_forwardEvents = []
if (! el._x_forwardEvents.includes(value)) el._x_forwardEvents.push(value)
}
let removeListener = on(el, value, modifiers, e => {
evaluate(() => {}, { scope: { '$event': e }, params: [e] })
})
cleanup(() => removeListener())
}))

View File

@ -0,0 +1,16 @@
import { closestRoot } from '../lifecycle'
import { directive } from '../directives'
function handler () {}
handler.inline = (el, { expression }, { cleanup }) => {
let root = closestRoot(el)
if (! root._x_refs) root._x_refs = {}
root._x_refs[expression] = el
cleanup(() => delete root._x_refs[expression])
}
directive('ref', handler)

View File

@ -0,0 +1,68 @@
import { evaluateLater } from '../evaluator'
import { directive } from '../directives'
import { mutateDom } from '../mutation'
import { once } from '../utils/once'
directive('show', (el, { modifiers, expression }, { effect }) => {
let evaluate = evaluateLater(el, expression)
// We're going to set this function on the element directly so that
// other plugins like "Collapse" can overwrite them with their own logic.
if (! el._x_doHide) el._x_doHide = () => {
mutateDom(() => {
el.style.setProperty('display', 'none', modifiers.includes('important') ? 'important' : undefined)
})
}
if (! el._x_doShow) el._x_doShow = () => {
mutateDom(() => {
if (el.style.length === 1 && el.style.display === 'none') {
el.removeAttribute('style')
} else {
el.style.removeProperty('display')
}
})
}
let hide = () => {
el._x_doHide()
el._x_isShown = false
}
let show = () => {
el._x_doShow()
el._x_isShown = true
}
// We are wrapping this function in a setTimeout here to prevent
// a race condition from happening where elements that have a
// @click.away always view themselves as shown on the page.
let clickAwayCompatibleShow = () => setTimeout(show)
let toggle = once(
value => value ? show() : hide(),
value => {
if (typeof el._x_toggleAndCascadeWithTransitions === 'function') {
el._x_toggleAndCascadeWithTransitions(el, value, show, hide)
} else {
value ? clickAwayCompatibleShow() : hide()
}
}
)
let oldValue
let firstTime = true
effect(() => evaluate(value => {
// Let's make sure we only call this effect if the value changed.
// This prevents "blip" transitions. (1 tick out, then in)
if (! firstTime && value === oldValue) return
if (modifiers.includes('immediate')) value ? clickAwayCompatibleShow() : hide()
toggle(value)
oldValue = value
firstTime = false
}))
})

View File

@ -0,0 +1,85 @@
import { skipDuringClone } from "../clone"
import { directive } from "../directives"
import { initTree, destroyTree } from "../lifecycle"
import { mutateDom } from "../mutation"
import { addScopeToNode } from "../scope"
import { warn } from "../utils/warn"
directive('teleport', (el, { modifiers, expression }, { cleanup }) => {
if (el.tagName.toLowerCase() !== 'template') warn('x-teleport can only be used on a <template> tag', el)
let target = getTarget(expression)
let clone = el.content.cloneNode(true).firstElementChild
// Add reference to element on <template x-teleport, and visa versa.
el._x_teleport = clone
clone._x_teleportBack = el
// Add the key to the DOM so they can be more easily searched for and linked up...
el.setAttribute('data-teleport-template', true)
clone.setAttribute('data-teleport-target', true)
// Forward event listeners:
if (el._x_forwardEvents) {
el._x_forwardEvents.forEach(eventName => {
clone.addEventListener(eventName, e => {
e.stopPropagation()
el.dispatchEvent(new e.constructor(e.type, e))
})
})
}
addScopeToNode(clone, {}, el)
let placeInDom = (clone, target, modifiers) => {
if (modifiers.includes('prepend')) {
// insert element before the target
target.parentNode.insertBefore(clone, target)
} else if (modifiers.includes('append')) {
// insert element after the target
target.parentNode.insertBefore(clone, target.nextSibling)
} else {
// origin
target.appendChild(clone)
}
}
mutateDom(() => {
placeInDom(clone, target, modifiers)
skipDuringClone(() => {
initTree(clone)
})()
})
el._x_teleportPutBack = () => {
let target = getTarget(expression)
mutateDom(() => {
placeInDom(el._x_teleport, target, modifiers)
})
}
cleanup(() =>
mutateDom(() => {
clone.remove()
destroyTree(clone)
})
)
})
let teleportContainerDuringClone = document.createElement('div')
function getTarget(expression) {
let target = skipDuringClone(() => {
return document.querySelector(expression)
}, () => {
return teleportContainerDuringClone
})()
if (! target) warn(`Cannot find x-teleport element for selector: "${expression}"`)
return target
}

View File

@ -0,0 +1,14 @@
import { directive } from '../directives'
import { mutateDom } from '../mutation'
directive('text', (el, { expression }, { effect, evaluateLater }) => {
let evaluate = evaluateLater(expression)
effect(() => {
evaluate(value => {
mutateDom(() => {
el.textContent = value
})
})
})
})

View File

@ -0,0 +1,335 @@
import { releaseNextTicks, holdNextTicks } from '../nextTick'
import { setClasses } from '../utils/classes'
import { setStyles } from '../utils/styles'
import { directive } from '../directives'
import { mutateDom } from '../mutation'
import { once } from '../utils/once'
directive('transition', (el, { value, modifiers, expression }, { evaluate }) => {
if (typeof expression === 'function') expression = evaluate(expression)
if (expression === false) return
if (!expression || typeof expression === 'boolean') {
registerTransitionsFromHelper(el, modifiers, value)
} else {
registerTransitionsFromClassString(el, expression, value)
}
})
function registerTransitionsFromClassString(el, classString, stage) {
registerTransitionObject(el, setClasses, '')
let directiveStorageMap = {
'enter': (classes) => { el._x_transition.enter.during = classes },
'enter-start': (classes) => { el._x_transition.enter.start = classes },
'enter-end': (classes) => { el._x_transition.enter.end = classes },
'leave': (classes) => { el._x_transition.leave.during = classes },
'leave-start': (classes) => { el._x_transition.leave.start = classes },
'leave-end': (classes) => { el._x_transition.leave.end = classes },
}
directiveStorageMap[stage](classString)
}
function registerTransitionsFromHelper(el, modifiers, stage) {
registerTransitionObject(el, setStyles)
let doesntSpecify = (! modifiers.includes('in') && ! modifiers.includes('out')) && ! stage
let transitioningIn = doesntSpecify || modifiers.includes('in') || ['enter'].includes(stage)
let transitioningOut = doesntSpecify || modifiers.includes('out') || ['leave'].includes(stage)
if (modifiers.includes('in') && ! doesntSpecify) {
modifiers = modifiers.filter((i, index) => index < modifiers.indexOf('out'))
}
if (modifiers.includes('out') && ! doesntSpecify) {
modifiers = modifiers.filter((i, index) => index > modifiers.indexOf('out'))
}
let wantsAll = ! modifiers.includes('opacity') && ! modifiers.includes('scale')
let wantsOpacity = wantsAll || modifiers.includes('opacity')
let wantsScale = wantsAll || modifiers.includes('scale')
let opacityValue = wantsOpacity ? 0 : 1
let scaleValue = wantsScale ? modifierValue(modifiers, 'scale', 95) / 100 : 1
let delay = modifierValue(modifiers, 'delay', 0) / 1000
let origin = modifierValue(modifiers, 'origin', 'center')
let property = 'opacity, transform'
let durationIn = modifierValue(modifiers, 'duration', 150) / 1000
let durationOut = modifierValue(modifiers, 'duration', 75) / 1000
let easing = `cubic-bezier(0.4, 0.0, 0.2, 1)`
if (transitioningIn) {
el._x_transition.enter.during = {
transformOrigin: origin,
transitionDelay: `${delay}s`,
transitionProperty: property,
transitionDuration: `${durationIn}s`,
transitionTimingFunction: easing,
}
el._x_transition.enter.start = {
opacity: opacityValue,
transform: `scale(${scaleValue})`,
}
el._x_transition.enter.end = {
opacity: 1,
transform: `scale(1)`,
}
}
if (transitioningOut) {
el._x_transition.leave.during = {
transformOrigin: origin,
transitionDelay: `${delay}s`,
transitionProperty: property,
transitionDuration: `${durationOut}s`,
transitionTimingFunction: easing,
}
el._x_transition.leave.start = {
opacity: 1,
transform: `scale(1)`,
}
el._x_transition.leave.end = {
opacity: opacityValue,
transform: `scale(${scaleValue})`,
}
}
}
function registerTransitionObject(el, setFunction, defaultValue = {}) {
if (! el._x_transition) el._x_transition = {
enter: { during: defaultValue, start: defaultValue, end: defaultValue },
leave: { during: defaultValue, start: defaultValue, end: defaultValue },
in(before = () => {}, after = () => {}) {
transition(el, setFunction, {
during: this.enter.during,
start: this.enter.start,
end: this.enter.end,
}, before, after)
},
out(before = () => {}, after = () => {}) {
transition(el, setFunction, {
during: this.leave.during,
start: this.leave.start,
end: this.leave.end,
}, before, after)
},
}
}
window.Element.prototype._x_toggleAndCascadeWithTransitions = function (el, value, show, hide) {
// We are running this function after one tick to prevent
// a race condition from happening where elements that have a
// @click.away always view themselves as shown on the page.
// If the tab is active, we prioritise requestAnimationFrame which plays
// nicely with nested animations otherwise we use setTimeout to make sure
// it keeps running in background. setTimeout has a lower priority in the
// event loop so it would skip nested transitions but when the tab is
// hidden, it's not relevant.
const nextTick = document.visibilityState === 'visible' ? requestAnimationFrame : setTimeout;
let clickAwayCompatibleShow = () => nextTick(show);
if (value) {
if (el._x_transition && (el._x_transition.enter || el._x_transition.leave)) {
// This fixes a bug where if you are only transitioning OUT and you are also using @click.outside
// the element when shown immediately starts transitioning out. There is a test in the manual
// transition test file for this: /tests/cypress/manual-transition-test.html
(el._x_transition.enter && (Object.entries(el._x_transition.enter.during).length || Object.entries(el._x_transition.enter.start).length || Object.entries(el._x_transition.enter.end).length))
? el._x_transition.in(show)
: clickAwayCompatibleShow()
} else {
el._x_transition
? el._x_transition.in(show)
: clickAwayCompatibleShow()
}
return
}
// Livewire depends on el._x_hidePromise.
el._x_hidePromise = el._x_transition
? new Promise((resolve, reject) => {
el._x_transition.out(() => {}, () => resolve(hide))
el._x_transitioning && el._x_transitioning.beforeCancel(() => reject({ isFromCancelledTransition: true }))
})
: Promise.resolve(hide)
queueMicrotask(() => {
let closest = closestHide(el)
if (closest) {
if (! closest._x_hideChildren) closest._x_hideChildren = []
closest._x_hideChildren.push(el)
} else {
nextTick(() => {
let hideAfterChildren = el => {
let carry = Promise.all([
el._x_hidePromise,
...(el._x_hideChildren || []).map(hideAfterChildren),
]).then(([i]) => i?.())
delete el._x_hidePromise
delete el._x_hideChildren
return carry
}
hideAfterChildren(el).catch((e) => {
if (! e.isFromCancelledTransition) throw e
})
})
}
})
}
function closestHide(el) {
let parent = el.parentNode
if (! parent) return
return parent._x_hidePromise ? parent : closestHide(parent)
}
export function transition(el, setFunction, { during, start, end } = {}, before = () => {}, after = () => {}) {
if (el._x_transitioning) el._x_transitioning.cancel()
if (Object.keys(during).length === 0 && Object.keys(start).length === 0 && Object.keys(end).length === 0) {
// Execute right away if there is no transition.
before(); after()
return
}
let undoStart, undoDuring, undoEnd
performTransition(el, {
start() {
undoStart = setFunction(el, start)
},
during() {
undoDuring = setFunction(el, during)
},
before,
end() {
undoStart()
undoEnd = setFunction(el, end)
},
after,
cleanup() {
undoDuring()
undoEnd()
},
})
}
export function performTransition(el, stages) {
// All transitions need to be truly "cancellable". Meaning we need to
// account for interruptions at ALL stages of the transitions and
// immediately run the rest of the transition.
let interrupted, reachedBefore, reachedEnd
let finish = once(() => {
mutateDom(() => {
interrupted = true
if (! reachedBefore) stages.before()
if (! reachedEnd) {
stages.end()
releaseNextTicks()
}
stages.after()
// Adding an "isConnected" check, in case the callback removed the element from the DOM.
if (el.isConnected) stages.cleanup()
delete el._x_transitioning
})
})
el._x_transitioning = {
beforeCancels: [],
beforeCancel(callback) { this.beforeCancels.push(callback) },
cancel: once(function () { while (this.beforeCancels.length) { this.beforeCancels.shift()() }; finish(); }),
finish,
}
mutateDom(() => {
stages.start()
stages.during()
})
holdNextTicks()
requestAnimationFrame(() => {
if (interrupted) return
// Note: Safari's transitionDuration property will list out comma separated transition durations
// for every single transition property. Let's grab the first one and call it a day.
let duration = Number(getComputedStyle(el).transitionDuration.replace(/,.*/, '').replace('s', '')) * 1000
let delay = Number(getComputedStyle(el).transitionDelay.replace(/,.*/, '').replace('s', '')) * 1000
if (duration === 0) duration = Number(getComputedStyle(el).animationDuration.replace('s', '')) * 1000
mutateDom(() => {
stages.before()
})
reachedBefore = true
requestAnimationFrame(() => {
if (interrupted) return
mutateDom(() => {
stages.end()
})
releaseNextTicks()
setTimeout(el._x_transitioning.finish, duration + delay)
reachedEnd = true
})
})
}
export function modifierValue(modifiers, key, fallback) {
// If the modifier isn't present, use the default.
if (modifiers.indexOf(key) === -1) return fallback
// If it IS present, grab the value after it: x-show.transition.duration.500ms
const rawValue = modifiers[modifiers.indexOf(key) + 1]
if (! rawValue) return fallback
if (key === 'scale') {
// Check if the very next value is NOT a number and return the fallback.
// If x-show.transition.scale, we'll use the default scale value.
// That is how a user opts out of the opacity transition.
if (isNaN(rawValue)) return fallback
}
if (key === 'duration' || key === 'delay') {
// Support x-transition.duration.500ms && duration.500
let match = rawValue.match(/([0-9]+)ms/)
if (match) return match[1]
}
if (key === 'origin') {
// Support chaining origin directions: x-show.transition.top.right
if (['top', 'right', 'left', 'center', 'bottom'].includes(modifiers[modifiers.indexOf(key) + 2])) {
return [rawValue, modifiers[modifiers.indexOf(key) + 2]].join(' ')
}
}
return rawValue
}

View File

@ -0,0 +1,41 @@
import { effect, release } from './reactivity'
export function entangle({ get: outerGet, set: outerSet }, { get: innerGet, set: innerSet }) {
let firstRun = true
let outerHash
let innerHash
let reference = effect(() => {
let outer = outerGet()
let inner = innerGet()
if (firstRun) {
innerSet(cloneIfObject(outer))
firstRun = false
} else {
let outerHashLatest = JSON.stringify(outer)
let innerHashLatest = JSON.stringify(inner)
if (outerHashLatest !== outerHash) { // If outer changed...
innerSet(cloneIfObject(outer))
} else if (outerHashLatest !== innerHashLatest) { // If inner changed...
outerSet(cloneIfObject(inner))
} else { // If nothing changed...
// Prevent an infinite loop...
}
}
outerHash = JSON.stringify(outerGet())
innerHash = JSON.stringify(innerGet())
})
return () => {
release(reference)
}
}
function cloneIfObject(value) {
return typeof value === 'object'
? JSON.parse(JSON.stringify(value))
: value
}

View File

@ -0,0 +1,151 @@
import { closestDataStack, mergeProxies } from './scope'
import { injectMagics } from './magics'
import { tryCatch, handleError } from './utils/error'
let shouldAutoEvaluateFunctions = true
export function dontAutoEvaluateFunctions(callback) {
let cache = shouldAutoEvaluateFunctions
shouldAutoEvaluateFunctions = false
let result = callback()
shouldAutoEvaluateFunctions = cache
return result
}
export function evaluate(el, expression, extras = {}) {
let result
evaluateLater(el, expression)(value => result = value, extras)
return result
}
export function evaluateLater(...args) {
return theEvaluatorFunction(...args)
}
let theEvaluatorFunction = normalEvaluator
export function setEvaluator(newEvaluator) {
theEvaluatorFunction = newEvaluator
}
export function normalEvaluator(el, expression) {
let overriddenMagics = {}
injectMagics(overriddenMagics, el)
let dataStack = [overriddenMagics, ...closestDataStack(el)]
let evaluator = (typeof expression === 'function')
? generateEvaluatorFromFunction(dataStack, expression)
: generateEvaluatorFromString(dataStack, expression, el)
return tryCatch.bind(null, el, expression, evaluator)
}
export function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {}, { scope = {}, params = [] } = {}) => {
let result = func.apply(mergeProxies([scope, ...dataStack]), params)
runIfTypeOfFunction(receiver, result)
}
}
let evaluatorMemo = {}
function generateFunctionFromString(expression, el) {
if (evaluatorMemo[expression]) {
return evaluatorMemo[expression]
}
let AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
// Some expressions that are useful in Alpine are not valid as the right side of an expression.
// Here we'll detect if the expression isn't valid for an assignment and wrap it in a self-
// calling function so that we don't throw an error AND a "return" statement can b e used.
let rightSideSafeExpression = 0
// Support expressions starting with "if" statements like: "if (...) doSomething()"
|| /^[\n\s]*if.*\(.*\)/.test(expression.trim())
// Support expressions starting with "let/const" like: "let foo = 'bar'"
|| /^(let|const)\s/.test(expression.trim())
? `(async()=>{ ${expression} })()`
: expression
const safeAsyncFunction = () => {
try {
let func = new AsyncFunction(
["__self", "scope"],
`with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`
)
Object.defineProperty(func, "name", {
value: `[Alpine] ${expression}`,
})
return func
} catch ( error ) {
handleError( error, el, expression )
return Promise.resolve()
}
}
let func = safeAsyncFunction()
evaluatorMemo[expression] = func
return func
}
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el)
return (receiver = () => {}, { scope = {}, params = [] } = {}) => {
func.result = undefined
func.finished = false
// Run the function.
let completeScope = mergeProxies([ scope, ...dataStack ])
if (typeof func === 'function' ) {
let promise = func(func, completeScope).catch((error) => handleError(error, el, expression))
// Check if the function ran synchronously,
if (func.finished) {
// Return the immediate result.
runIfTypeOfFunction(receiver, func.result, completeScope, params, el)
// Once the function has run, we clear func.result so we don't create
// memory leaks. func is stored in the evaluatorMemo and every time
// it runs, it assigns the evaluated expression to result which could
// potentially store a reference to the DOM element that will be removed later on.
func.result = undefined
} else {
// If not, return the result when the promise resolves.
promise.then(result => {
runIfTypeOfFunction(receiver, result, completeScope, params, el)
}).catch( error => handleError( error, el, expression ) )
.finally( () => func.result = undefined )
}
}
}
}
export function runIfTypeOfFunction(receiver, value, scope, params, el) {
if (shouldAutoEvaluateFunctions && typeof value === 'function') {
let result = value.apply(scope, params)
if (result instanceof Promise) {
result.then(i => runIfTypeOfFunction(receiver, i, scope, params)).catch( error => handleError( error, el, value ) )
} else {
receiver(result)
}
} else if (typeof value === 'object' && value instanceof Promise) {
value.then(i => receiver(i))
} else {
receiver(value)
}
}

View File

@ -0,0 +1,20 @@
import { findClosest } from './lifecycle'
let globalIdMemo = {}
export function findAndIncrementId(name) {
if (! globalIdMemo[name]) globalIdMemo[name] = 0
return ++globalIdMemo[name]
}
export function closestIdRoot(el, name) {
return findClosest(el, element => {
if (element._x_ids && element._x_ids[name]) return true
})
}
export function setIdRoot(el, name) {
if (! el._x_ids) el._x_ids = {}
if (! el._x_ids[name]) el._x_ids[name] = findAndIncrementId(name)
}

View File

@ -0,0 +1,74 @@
/**
* _
* /\ | | (_) (_)
* / \ | |_ __ _ _ __ ___ _ ___
* / /\ \ | | '_ \| | '_ \ / _ \ | / __|
* / ____ \| | |_) | | | | | __/_| \__ \
* /_/ \_\_| .__/|_|_| |_|\___(_) |___/
* | | _/ |
* |_| |__/
*
* Let's build Alpine together. It's easier than you think.
* For starters, we'll import Alpine's core. This is the
* object that will expose all of Alpine's public API.
*/
import Alpine from './alpine'
/**
* _______________________________________________________
* The Evaluator
* -------------------------------------------------------
*
* Now we're ready to bootstrap Alpine's evaluation system.
* It's the function that converts raw JavaScript string
* expressions like @click="toggle()", into actual JS.
*/
import { normalEvaluator } from './evaluator'
Alpine.setEvaluator(normalEvaluator)
/**
* _______________________________________________________
* The Reactivity Engine
* -------------------------------------------------------
*
* This is the reactivity core of Alpine. It's the part of
* Alpine that triggers an element with x-text="message"
* to update its inner text when "message" is changed.
*/
import { reactive, effect, stop, toRaw } from '@vue/reactivity'
Alpine.setReactivityEngine({ reactive, effect, release: stop, raw: toRaw })
/**
* _______________________________________________________
* The Magics
* -------------------------------------------------------
*
* Yeah, we're calling them magics here like they're nouns.
* These are the properties that are magically available
* to all the Alpine expressions, within your web app.
*/
import './magics/index'
/**
* _______________________________________________________
* The Directives
* -------------------------------------------------------
*
* Now that the core is all set up, we can register Alpine
* directives like x-text or x-on that form the basis of
* how Alpine adds behavior to an app's static markup.
*/
import './directives/index'
/**
* _______________________________________________________
* The Alpine Global
* -------------------------------------------------------
*
* Now that we have set everything up internally, anything
* Alpine-related that will need to be accessed on-going
* will be made available through the "Alpine" global.
*/
export default Alpine

View File

@ -0,0 +1,78 @@
// Warning: The concept of "interceptors" in Alpine is not public API and is subject to change
// without tagging a major release.
export function initInterceptors(data) {
let isObject = val => typeof val === 'object' && !Array.isArray(val) && val !== null
let recurse = (obj, basePath = '') => {
Object.entries(Object.getOwnPropertyDescriptors(obj)).forEach(([key, { value, enumerable }]) => {
// Skip getters.
if (enumerable === false || value === undefined) return
if (typeof value === 'object' && value !== null && value.__v_skip) return
let path = basePath === '' ? key : `${basePath}.${key}`
if (typeof value === 'object' && value !== null && value._x_interceptor) {
obj[key] = value.initialize(data, path, key)
} else {
if (isObject(value) && value !== obj && ! (value instanceof Element)) {
recurse(value, path)
}
}
})
}
return recurse(data)
}
export function interceptor(callback, mutateObj = () => {}) {
let obj = {
initialValue: undefined,
_x_interceptor: true,
initialize(data, path, key) {
return callback(this.initialValue, () => get(data, path), (value) => set(data, path, value), path, key)
}
}
mutateObj(obj)
return initialValue => {
if (typeof initialValue === 'object' && initialValue !== null && initialValue._x_interceptor) {
// Support nesting interceptors.
let initialize = obj.initialize.bind(obj)
obj.initialize = (data, path, key) => {
let innerValue = initialValue.initialize(data, path, key)
obj.initialValue = innerValue
return initialize(data, path, key)
}
} else {
obj.initialValue = initialValue
}
return obj
}
}
function get(obj, path) {
return path.split('.').reduce((carry, segment) => carry[segment], obj)
}
function set(obj, path, value) {
if (typeof path === 'string') path = path.split('.')
if (path.length === 1) obj[path[0]] = value;
else if (path.length === 0) throw error;
else {
if (obj[path[0]])
return set(obj[path[0]], path.slice(1), value);
else {
obj[path[0]] = {};
return set(obj[path[0]], path.slice(1), value);
}
}
}

View File

@ -0,0 +1,138 @@
import { startObservingMutations, onAttributesAdded, onElAdded, onElRemoved, cleanupAttributes, cleanupElement } from "./mutation"
import { deferHandlingDirectives, directiveExists, directives } from "./directives"
import { dispatch } from './utils/dispatch'
import { walk } from "./utils/walk"
import { warn } from './utils/warn'
let started = false
export function start() {
if (started) warn('Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems.')
started = true
if (! document.body) warn('Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine\'s `<script>` tag?')
dispatch(document, 'alpine:init')
dispatch(document, 'alpine:initializing')
startObservingMutations()
onElAdded(el => initTree(el, walk))
onElRemoved(el => destroyTree(el))
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach(handle => handle())
})
let outNestedComponents = el => ! closestRoot(el.parentElement, true)
Array.from(document.querySelectorAll(allSelectors().join(',')))
.filter(outNestedComponents)
.forEach(el => {
initTree(el)
})
dispatch(document, 'alpine:initialized')
setTimeout(() => {
warnAboutMissingPlugins()
})
}
let rootSelectorCallbacks = []
let initSelectorCallbacks = []
export function rootSelectors() {
return rootSelectorCallbacks.map(fn => fn())
}
export function allSelectors() {
return rootSelectorCallbacks.concat(initSelectorCallbacks).map(fn => fn())
}
export function addRootSelector(selectorCallback) { rootSelectorCallbacks.push(selectorCallback) }
export function addInitSelector(selectorCallback) { initSelectorCallbacks.push(selectorCallback) }
export function closestRoot(el, includeInitSelectors = false) {
return findClosest(el, element => {
const selectors = includeInitSelectors ? allSelectors() : rootSelectors()
if (selectors.some(selector => element.matches(selector))) return true
})
}
export function findClosest(el, callback) {
if (! el) return
if (callback(el)) return el
// Support crawling up teleports.
if (el._x_teleportBack) el = el._x_teleportBack
if (! el.parentElement) return
return findClosest(el.parentElement, callback)
}
export function isRoot(el) {
return rootSelectors().some(selector => el.matches(selector))
}
let initInterceptors = []
export function interceptInit(callback) { initInterceptors.push(callback) }
let markerDispenser = 1
export function initTree(el, walker = walk, intercept = () => {}) {
// Don't init a tree within a parent that is being ignored...
if (findClosest(el, i => i._x_ignore)) return
deferHandlingDirectives(() => {
walker(el, (el, skip) => {
// If the element has a marker, it's already been initialized...
if (el._x_marker) return
intercept(el, skip)
initInterceptors.forEach(i => i(el, skip))
directives(el, el.attributes).forEach(handle => handle())
// Add a marker to the element so we can tell if it's been initialized...
// This is important so that we can prevent double-initialization of
// elements that are moved around on the page.
if (!el._x_ignore) el._x_marker = markerDispenser++
el._x_ignore && skip()
})
})
}
export function destroyTree(root, walker = walk) {
walker(root, el => {
cleanupElement(el)
cleanupAttributes(el)
delete el._x_marker
})
}
function warnAboutMissingPlugins() {
let pluginDirectives = [
[ 'ui', 'dialog', ['[x-dialog], [x-popover]'] ],
[ 'anchor', 'anchor', ['[x-anchor]'] ],
[ 'sort', 'sort', ['[x-sort]'] ],
]
pluginDirectives.forEach(([ plugin, directive, selectors ]) => {
if (directiveExists(directive)) return
selectors.some(selector => {
if (document.querySelector(selector)) {
warn(`found "${selector}", but missing ${plugin} plugin`)
return true
}
})
})
}

View File

@ -0,0 +1,34 @@
import { getElementBoundUtilities } from './directives'
import { interceptor } from './interceptor'
import { onElRemoved } from './mutation'
let magics = {}
export function magic(name, callback) {
magics[name] = callback
}
export function injectMagics(obj, el) {
let memoizedUtilities = getUtilities(el)
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
return callback(el, memoizedUtilities);
},
enumerable: false,
})
})
return obj
}
export function getUtilities(el) {
let [utilities, cleanup] = getElementBoundUtilities(el)
let utils = { interceptor, ...utilities }
onElRemoved(el, cleanup)
return utils;
}

View File

@ -0,0 +1,4 @@
import { scope } from '../scope'
import { magic } from '../magics'
magic('data', el => scope(el))

View File

@ -0,0 +1,4 @@
import { dispatch } from '../utils/dispatch'
import { magic } from '../magics'
magic('dispatch', el => dispatch.bind(dispatch, el))

Some files were not shown because too many files have changed in this diff Show More