├── index.html ├── package.json ├── LICENSE ├── README.md ├── .gitignore ├── index.js └── yarn.lock /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dirty-check", 3 | "version": "0.0.0", 4 | "description": "reactivity system with dirty checking", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "serve ." 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/yisar/dirty-checking.git" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/yisar/dirty-checking/issues" 19 | }, 20 | "homepage": "https://github.com/yisar/dirty-checking#readme", 21 | "devDependencies": { 22 | "serve": "^11.3.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 伊撒尔 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dirty-check 2 | 3 | Tiny reactivity system with dirty checking. 4 | 5 | ### Motivation 6 | 7 | [点我](https://zhuanlan.zhihu.com/p/278238753) 8 | 9 | 由于基于`对象劫持`的响应式方案存在 ref 的缺陷,不利于组合……我们企图找到一种替代方案 10 | 11 | 这个仓库提供了一种脏检查的思路,它没有 ref 的缺陷,没有 hooks 的限制,对组合更有利 12 | 13 | ### Usage 14 | 15 | ```js 16 | import { ref, computed, invalidate } from './index.js' 17 | const count = ref(0) 18 | const double = computed(() => count() * 2) 19 | count(1) 20 | count(2) 21 | 22 | invalidate() // 开始脏检查 23 | console.log(double()) // 4 24 | ``` 25 | 26 | ### Implement 27 | 28 | 脏检查也是一种依赖收集,每调用一次 invalidate 则开启一轮的脏检查,此时 computed 会重新计算 29 | 30 | 和 angularjs 不同,这个仓库使用了`有向图`的数据结构,约定脏检查是单向的,性能显著提升 31 | 32 | - vs setState 33 | 34 | 脏检查和 setState 是类似的,只是 setState 必须利用闭包缓存组件实例,而脏检查的响应式不需要和组件强绑定 35 | 36 | ```js 37 | const double = computed(() => count() * 2) 38 | 39 | const stateLessComponent = () => 40 | ``` 41 | 42 | - vs Proxy 43 | 44 | 脏检查和对象劫持也是类似的,一般来讲,脏检查性能会稍差,API 也低级些,但是没有 ref 的限制 45 | 46 | ### Compiler 47 | 48 | 建议和编译手段结合使用,脏检查的思路非常适合走编译路线 49 | 50 | ```html 51 | 59 | 60 | 61 | ``` 62 | 63 | 大约编译成这个样子: 64 | 65 | ```html 66 | 74 | 75 | 76 | ``` 77 | 78 | 不需要改变语义,不需要任何语法糖,runtime 也非常轻量 79 | 80 | p.s. 81 | 82 | 俺不开倒车,不同的机制有不同的优势,在 vue composition API 和 hooks API 都出现了限制的前提下 83 | 84 | 脏检查恰好可以规避这些限制,可以说最适合组合的方案了 85 | 86 | ### License 87 | 88 | MIT @132 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | let count = 1 2 | let activeDeps = null 3 | 4 | export function clock() { 5 | return count 6 | } 7 | 8 | export function advanceClock() { 9 | count++ 10 | } 11 | 12 | export const ref = (v) => { 13 | let value = { t: clock(), v } 14 | return (n) => { 15 | return n ? set(value, n) : get(value) 16 | } 17 | } 18 | 19 | export function restore(deps) { 20 | activeDeps = deps 21 | } 22 | 23 | export function set(v, n) { 24 | v.t = clock() 25 | v.v = n 26 | return v.v 27 | } 28 | 29 | export function get(v) { 30 | if (activeDeps === null) { 31 | activeDeps = [clock(), v] 32 | } else { 33 | activeDeps.push(v) 34 | } 35 | return typeof v === 'function' ? v : v.v 36 | } 37 | 38 | export function dirtyCheck(deps) { 39 | if (deps == null) return true 40 | const t = deps[0] 41 | for (let i = 1; i < deps.length; i++) { 42 | const v = deps[i] 43 | if (typeof v === 'object') { 44 | if (v.t > t) { 45 | return true 46 | } 47 | } else if (v(true, t) === true) { 48 | return true 49 | } 50 | } 51 | return false 52 | } 53 | 54 | export function save() { 55 | const deps = activeDeps 56 | activeDeps = null 57 | return deps 58 | } 59 | 60 | export function computed(fn) { 61 | let lastdirtyCheck = 0 62 | let lastUpdate = 0 63 | let value = void 0 64 | let deps = null 65 | return (token, time) => { 66 | const now = clock() 67 | if (lastdirtyCheck < now) { 68 | lastdirtyCheck = now 69 | if (dirtyCheck(deps) === true) { 70 | const prevDeps = save() 71 | const nextValue = fn(value) 72 | deps = save() 73 | restore(prevDeps) 74 | if (value !== nextValue) { 75 | value = nextValue 76 | lastUpdate = now 77 | } 78 | } 79 | } 80 | return token ? lastUpdate > time : value 81 | } 82 | } 83 | 84 | export function selector(fn) { 85 | let lastdirtyCheck = 0 86 | let lastUpdate = 0 87 | let value = void 0 88 | return () => { 89 | const now = clock() 90 | if (lastdirtyCheck < now) { 91 | lastdirtyCheck = now 92 | const nextValue = fn(value) 93 | if (value !== nextValue) { 94 | value = nextValue 95 | lastUpdate = now 96 | } 97 | } 98 | return token ? lastUpdate > time : value 99 | } 100 | } 101 | 102 | const defer = 103 | typeof Promise === 'function' 104 | ? function (cb) { 105 | Promise.resolve().then(cb) 106 | } 107 | : setTimeout 108 | 109 | export function invalidate(render) { 110 | try { 111 | defer(render) 112 | } finally { 113 | advanceClock() 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@zeit/schemas@2.6.0": 6 | version "2.6.0" 7 | resolved "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3" 8 | integrity sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg== 9 | 10 | accepts@~1.3.5: 11 | version "1.3.7" 12 | resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" 13 | integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== 14 | dependencies: 15 | mime-types "~2.1.24" 16 | negotiator "0.6.2" 17 | 18 | ajv@6.5.3: 19 | version "6.5.3" 20 | resolved "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9" 21 | integrity sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg== 22 | dependencies: 23 | fast-deep-equal "^2.0.1" 24 | fast-json-stable-stringify "^2.0.0" 25 | json-schema-traverse "^0.4.1" 26 | uri-js "^4.2.2" 27 | 28 | ansi-align@^2.0.0: 29 | version "2.0.0" 30 | resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" 31 | integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= 32 | dependencies: 33 | string-width "^2.0.0" 34 | 35 | ansi-regex@^3.0.0: 36 | version "3.0.0" 37 | resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 38 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 39 | 40 | ansi-styles@^3.2.1: 41 | version "3.2.1" 42 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 43 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 44 | dependencies: 45 | color-convert "^1.9.0" 46 | 47 | arch@^2.1.0: 48 | version "2.2.0" 49 | resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" 50 | integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== 51 | 52 | arg@2.0.0: 53 | version "2.0.0" 54 | resolved "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz#c06e7ff69ab05b3a4a03ebe0407fac4cba657545" 55 | integrity sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w== 56 | 57 | balanced-match@^1.0.0: 58 | version "1.0.0" 59 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 60 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 61 | 62 | boxen@1.3.0: 63 | version "1.3.0" 64 | resolved "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" 65 | integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== 66 | dependencies: 67 | ansi-align "^2.0.0" 68 | camelcase "^4.0.0" 69 | chalk "^2.0.1" 70 | cli-boxes "^1.0.0" 71 | string-width "^2.0.0" 72 | term-size "^1.2.0" 73 | widest-line "^2.0.0" 74 | 75 | brace-expansion@^1.1.7: 76 | version "1.1.11" 77 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 78 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 79 | dependencies: 80 | balanced-match "^1.0.0" 81 | concat-map "0.0.1" 82 | 83 | bytes@3.0.0: 84 | version "3.0.0" 85 | resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" 86 | integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= 87 | 88 | camelcase@^4.0.0: 89 | version "4.1.0" 90 | resolved "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" 91 | integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= 92 | 93 | chalk@2.4.1: 94 | version "2.4.1" 95 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" 96 | integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== 97 | dependencies: 98 | ansi-styles "^3.2.1" 99 | escape-string-regexp "^1.0.5" 100 | supports-color "^5.3.0" 101 | 102 | chalk@^2.0.1: 103 | version "2.4.2" 104 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 105 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 106 | dependencies: 107 | ansi-styles "^3.2.1" 108 | escape-string-regexp "^1.0.5" 109 | supports-color "^5.3.0" 110 | 111 | cli-boxes@^1.0.0: 112 | version "1.0.0" 113 | resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" 114 | integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= 115 | 116 | clipboardy@1.2.3: 117 | version "1.2.3" 118 | resolved "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" 119 | integrity sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA== 120 | dependencies: 121 | arch "^2.1.0" 122 | execa "^0.8.0" 123 | 124 | color-convert@^1.9.0: 125 | version "1.9.3" 126 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 127 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 128 | dependencies: 129 | color-name "1.1.3" 130 | 131 | color-name@1.1.3: 132 | version "1.1.3" 133 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 134 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 135 | 136 | compressible@~2.0.14: 137 | version "2.0.18" 138 | resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" 139 | integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== 140 | dependencies: 141 | mime-db ">= 1.43.0 < 2" 142 | 143 | compression@1.7.3: 144 | version "1.7.3" 145 | resolved "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db" 146 | integrity sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg== 147 | dependencies: 148 | accepts "~1.3.5" 149 | bytes "3.0.0" 150 | compressible "~2.0.14" 151 | debug "2.6.9" 152 | on-headers "~1.0.1" 153 | safe-buffer "5.1.2" 154 | vary "~1.1.2" 155 | 156 | concat-map@0.0.1: 157 | version "0.0.1" 158 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 159 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 160 | 161 | content-disposition@0.5.2: 162 | version "0.5.2" 163 | resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" 164 | integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= 165 | 166 | cross-spawn@^5.0.1: 167 | version "5.1.0" 168 | resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 169 | integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= 170 | dependencies: 171 | lru-cache "^4.0.1" 172 | shebang-command "^1.2.0" 173 | which "^1.2.9" 174 | 175 | debug@2.6.9: 176 | version "2.6.9" 177 | resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 178 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 179 | dependencies: 180 | ms "2.0.0" 181 | 182 | deep-extend@^0.6.0: 183 | version "0.6.0" 184 | resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" 185 | integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== 186 | 187 | escape-string-regexp@^1.0.5: 188 | version "1.0.5" 189 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 190 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 191 | 192 | execa@^0.7.0: 193 | version "0.7.0" 194 | resolved "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" 195 | integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= 196 | dependencies: 197 | cross-spawn "^5.0.1" 198 | get-stream "^3.0.0" 199 | is-stream "^1.1.0" 200 | npm-run-path "^2.0.0" 201 | p-finally "^1.0.0" 202 | signal-exit "^3.0.0" 203 | strip-eof "^1.0.0" 204 | 205 | execa@^0.8.0: 206 | version "0.8.0" 207 | resolved "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" 208 | integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= 209 | dependencies: 210 | cross-spawn "^5.0.1" 211 | get-stream "^3.0.0" 212 | is-stream "^1.1.0" 213 | npm-run-path "^2.0.0" 214 | p-finally "^1.0.0" 215 | signal-exit "^3.0.0" 216 | strip-eof "^1.0.0" 217 | 218 | fast-deep-equal@^2.0.1: 219 | version "2.0.1" 220 | resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 221 | integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= 222 | 223 | fast-json-stable-stringify@^2.0.0: 224 | version "2.1.0" 225 | resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 226 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 227 | 228 | fast-url-parser@1.1.3: 229 | version "1.1.3" 230 | resolved "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" 231 | integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= 232 | dependencies: 233 | punycode "^1.3.2" 234 | 235 | get-stream@^3.0.0: 236 | version "3.0.0" 237 | resolved "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 238 | integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= 239 | 240 | has-flag@^3.0.0: 241 | version "3.0.0" 242 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 243 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 244 | 245 | ini@~1.3.0: 246 | version "1.3.5" 247 | resolved "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" 248 | integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== 249 | 250 | is-fullwidth-code-point@^2.0.0: 251 | version "2.0.0" 252 | resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 253 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 254 | 255 | is-stream@^1.1.0: 256 | version "1.1.0" 257 | resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 258 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 259 | 260 | isexe@^2.0.0: 261 | version "2.0.0" 262 | resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 263 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 264 | 265 | json-schema-traverse@^0.4.1: 266 | version "0.4.1" 267 | resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 268 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 269 | 270 | lru-cache@^4.0.1: 271 | version "4.1.5" 272 | resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" 273 | integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== 274 | dependencies: 275 | pseudomap "^1.0.2" 276 | yallist "^2.1.2" 277 | 278 | mime-db@1.44.0: 279 | version "1.44.0" 280 | resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" 281 | integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== 282 | 283 | "mime-db@>= 1.43.0 < 2": 284 | version "1.45.0" 285 | resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" 286 | integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== 287 | 288 | mime-db@~1.33.0: 289 | version "1.33.0" 290 | resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" 291 | integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== 292 | 293 | mime-types@2.1.18: 294 | version "2.1.18" 295 | resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" 296 | integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== 297 | dependencies: 298 | mime-db "~1.33.0" 299 | 300 | mime-types@~2.1.24: 301 | version "2.1.27" 302 | resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" 303 | integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== 304 | dependencies: 305 | mime-db "1.44.0" 306 | 307 | minimatch@3.0.4: 308 | version "3.0.4" 309 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 310 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 311 | dependencies: 312 | brace-expansion "^1.1.7" 313 | 314 | minimist@^1.2.0: 315 | version "1.2.5" 316 | resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 317 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 318 | 319 | ms@2.0.0: 320 | version "2.0.0" 321 | resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 322 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 323 | 324 | negotiator@0.6.2: 325 | version "0.6.2" 326 | resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" 327 | integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== 328 | 329 | npm-run-path@^2.0.0: 330 | version "2.0.2" 331 | resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 332 | integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= 333 | dependencies: 334 | path-key "^2.0.0" 335 | 336 | on-headers@~1.0.1: 337 | version "1.0.2" 338 | resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" 339 | integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== 340 | 341 | p-finally@^1.0.0: 342 | version "1.0.0" 343 | resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 344 | integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= 345 | 346 | path-is-inside@1.0.2: 347 | version "1.0.2" 348 | resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 349 | integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= 350 | 351 | path-key@^2.0.0: 352 | version "2.0.1" 353 | resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 354 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 355 | 356 | path-to-regexp@2.2.1: 357 | version "2.2.1" 358 | resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" 359 | integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== 360 | 361 | pseudomap@^1.0.2: 362 | version "1.0.2" 363 | resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 364 | integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= 365 | 366 | punycode@^1.3.2: 367 | version "1.4.1" 368 | resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 369 | integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= 370 | 371 | punycode@^2.1.0: 372 | version "2.1.1" 373 | resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 374 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 375 | 376 | range-parser@1.2.0: 377 | version "1.2.0" 378 | resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" 379 | integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= 380 | 381 | rc@^1.0.1, rc@^1.1.6: 382 | version "1.2.8" 383 | resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" 384 | integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== 385 | dependencies: 386 | deep-extend "^0.6.0" 387 | ini "~1.3.0" 388 | minimist "^1.2.0" 389 | strip-json-comments "~2.0.1" 390 | 391 | registry-auth-token@3.3.2: 392 | version "3.3.2" 393 | resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" 394 | integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== 395 | dependencies: 396 | rc "^1.1.6" 397 | safe-buffer "^5.0.1" 398 | 399 | registry-url@3.1.0: 400 | version "3.1.0" 401 | resolved "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" 402 | integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= 403 | dependencies: 404 | rc "^1.0.1" 405 | 406 | safe-buffer@5.1.2: 407 | version "5.1.2" 408 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 409 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 410 | 411 | safe-buffer@^5.0.1: 412 | version "5.2.1" 413 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 414 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 415 | 416 | serve-handler@6.1.3: 417 | version "6.1.3" 418 | resolved "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" 419 | integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== 420 | dependencies: 421 | bytes "3.0.0" 422 | content-disposition "0.5.2" 423 | fast-url-parser "1.1.3" 424 | mime-types "2.1.18" 425 | minimatch "3.0.4" 426 | path-is-inside "1.0.2" 427 | path-to-regexp "2.2.1" 428 | range-parser "1.2.0" 429 | 430 | serve@^11.3.2: 431 | version "11.3.2" 432 | resolved "https://registry.npmjs.org/serve/-/serve-11.3.2.tgz#b905e980616feecd170e51c8f979a7b2374098f5" 433 | integrity sha512-yKWQfI3xbj/f7X1lTBg91fXBP0FqjJ4TEi+ilES5yzH0iKJpN5LjNb1YzIfQg9Rqn4ECUS2SOf2+Kmepogoa5w== 434 | dependencies: 435 | "@zeit/schemas" "2.6.0" 436 | ajv "6.5.3" 437 | arg "2.0.0" 438 | boxen "1.3.0" 439 | chalk "2.4.1" 440 | clipboardy "1.2.3" 441 | compression "1.7.3" 442 | serve-handler "6.1.3" 443 | update-check "1.5.2" 444 | 445 | shebang-command@^1.2.0: 446 | version "1.2.0" 447 | resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 448 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 449 | dependencies: 450 | shebang-regex "^1.0.0" 451 | 452 | shebang-regex@^1.0.0: 453 | version "1.0.0" 454 | resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 455 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 456 | 457 | signal-exit@^3.0.0: 458 | version "3.0.3" 459 | resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 460 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 461 | 462 | string-width@^2.0.0, string-width@^2.1.1: 463 | version "2.1.1" 464 | resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 465 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 466 | dependencies: 467 | is-fullwidth-code-point "^2.0.0" 468 | strip-ansi "^4.0.0" 469 | 470 | strip-ansi@^4.0.0: 471 | version "4.0.0" 472 | resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 473 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 474 | dependencies: 475 | ansi-regex "^3.0.0" 476 | 477 | strip-eof@^1.0.0: 478 | version "1.0.0" 479 | resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 480 | integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= 481 | 482 | strip-json-comments@~2.0.1: 483 | version "2.0.1" 484 | resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 485 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 486 | 487 | supports-color@^5.3.0: 488 | version "5.5.0" 489 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 490 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 491 | dependencies: 492 | has-flag "^3.0.0" 493 | 494 | term-size@^1.2.0: 495 | version "1.2.0" 496 | resolved "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" 497 | integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= 498 | dependencies: 499 | execa "^0.7.0" 500 | 501 | update-check@1.5.2: 502 | version "1.5.2" 503 | resolved "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz#2fe09f725c543440b3d7dabe8971f2d5caaedc28" 504 | integrity sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ== 505 | dependencies: 506 | registry-auth-token "3.3.2" 507 | registry-url "3.1.0" 508 | 509 | uri-js@^4.2.2: 510 | version "4.4.0" 511 | resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" 512 | integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== 513 | dependencies: 514 | punycode "^2.1.0" 515 | 516 | vary@~1.1.2: 517 | version "1.1.2" 518 | resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 519 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 520 | 521 | which@^1.2.9: 522 | version "1.3.1" 523 | resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 524 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 525 | dependencies: 526 | isexe "^2.0.0" 527 | 528 | widest-line@^2.0.0: 529 | version "2.0.1" 530 | resolved "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" 531 | integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== 532 | dependencies: 533 | string-width "^2.1.1" 534 | 535 | yallist@^2.1.2: 536 | version "2.1.2" 537 | resolved "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 538 | integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= 539 | --------------------------------------------------------------------------------