├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── package.json ├── packages ├── compiler-core │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── codegen.spec.ts.snap │ │ ├── codegen.spec.ts │ │ ├── parse.spec.ts │ │ └── transform.spec.ts │ ├── package.json │ └── src │ │ ├── ast.ts │ │ ├── codegen.ts │ │ ├── compile.ts │ │ ├── index.ts │ │ ├── parse.ts │ │ ├── runtimeHelpers.ts │ │ ├── transform.ts │ │ ├── transforms │ │ ├── transformElement.ts │ │ ├── transformExpression.ts │ │ └── transformText.ts │ │ └── utils.ts ├── reactivity │ ├── __tests__ │ │ ├── computed.spec.ts │ │ ├── effect.spec.ts │ │ ├── reactive.spec.ts │ │ ├── readonly.spec.ts │ │ ├── ref.spec.ts │ │ └── shallowReadonly.spec.ts │ ├── package.json │ └── src │ │ ├── baseHandler.ts │ │ ├── computed.ts │ │ ├── effect.ts │ │ ├── index.ts │ │ ├── reactive.ts │ │ └── ref.ts ├── runtime-core │ ├── package.json │ └── src │ │ ├── apiInject.ts │ │ ├── component.ts │ │ ├── componentEmit.ts │ │ ├── componentProps.ts │ │ ├── componentPublisInstalce.ts │ │ ├── componentSlots.ts │ │ ├── componentUpdateUtils.ts │ │ ├── createApp.ts │ │ ├── h.ts │ │ ├── helpers │ │ └── renderSlots.ts │ │ ├── index.ts │ │ ├── renderer.ts │ │ ├── scheduler.ts │ │ └── vnode.ts ├── runtime-dom │ ├── package.json │ └── src │ │ └── index.ts ├── shared │ ├── package.json │ └── src │ │ ├── ShapeFlags.ts │ │ ├── index.ts │ │ └── toDisplayString.ts └── vue │ ├── example │ ├── apiInject │ │ ├── App.js │ │ └── index.html │ ├── compiler-base │ │ ├── App.js │ │ ├── index.html │ │ └── main.js │ ├── componentEmit │ │ ├── App.js │ │ ├── Foo.js │ │ ├── index.html │ │ └── main.js │ ├── componentSlot │ │ ├── App.js │ │ ├── Foo.js │ │ ├── index.html │ │ └── main.js │ ├── componentUpdate │ │ ├── App.js │ │ ├── Child.js │ │ └── index.html │ ├── currentInstance │ │ ├── App.js │ │ ├── Foo.js │ │ ├── index.html │ │ └── main.js │ ├── customRenderer │ │ ├── App.js │ │ ├── index.html │ │ └── main.js │ ├── helloworld │ │ ├── App.js │ │ ├── Foo.js │ │ ├── index.html │ │ └── main.js │ ├── nexttick │ │ ├── App.js │ │ ├── index.html │ │ └── main.js │ ├── patchChildren │ │ ├── App.js │ │ ├── ArrayToArray.js │ │ ├── ArrayToText.js │ │ ├── TextToArray.js │ │ ├── TextToText.js │ │ ├── index.html │ │ └── main.js │ └── update │ │ ├── App.js │ │ ├── index.html │ │ └── main.js │ ├── package.json │ └── src │ └── index.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── rollup.config.js ├── tsconfig.json └── vitest.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /yarn.lock 3 | .idea 4 | .gitignore 5 | /packages/compiler-core/node_modules/ 6 | /packages/reactivity/node_modules/ 7 | /packages/runtime-core/node_modules/ 8 | /packages/runtime-dom/node_modules/ 9 | /packages/vue/node_modules/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 wumanho 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 | # micro-vue-next 2 | 3 | :dart: 完成 [vuejs/core](https://github.com/vuejs/core) 的基本实现 4 | 5 | :dart: 学习如何设计一个充满魔法的前端框架 6 | 7 | :dart: 记录并输出一些内容 8 | 9 |   10 | 11 | ## 如何使用 12 | 13 | ``` 14 | # 打包 15 | yarn build 16 | 17 | # 测试 18 | yarn test 19 | ``` 20 | 21 |   22 | 23 | 24 | ## 项目相关的博客 25 | 26 | [Vue3 源码中的 Reactivity 学习和思考](https://wumanho.cn/posts/vue3reactivity/) 27 | 28 | [Vue3 源码中的位运算](https://wumanho.cn/posts/vueshapeflags/) 29 | 30 |   31 | 32 | ## src/reactivity 响应式模块 33 | 34 | :star2: API:reactive 35 | 36 | :star2: API:ref 37 | 38 | :star2: API:readonly 39 | 40 | :star2: API:computed 41 | 42 | :star2: track:依赖收集 43 | 44 | :star2: trigger:依赖触发 45 | 46 | :star2: API:isReactive 47 | 48 | :star2: reactive 嵌套 49 | 50 | :star2: API:toRaw 51 | 52 | :star2: effect.scheduler 执行调度 53 | 54 | :star2: effect.stop 停止触发依赖 55 | 56 | :star2: API:isReadonly 57 | 58 | :star2: API:isProxy 59 | 60 | :star2: shallowReadonly 非嵌套只读 61 | 62 | :star2: API:proxyRefs 63 | 64 |   65 | 66 | ## src/runtime-core 渲染器和 runtime 67 | 68 | :star2: 支持组件类型 69 | 70 | :star2: 支持 element 类型 71 | 72 | :star2: 支持组件 props 73 | 74 | :star2: 支持 $el api 75 | 76 | :star2: setup 可获取 props 和 context 77 | 78 | :star2: emit 自定义事件 79 | 80 | :star2: 组件通过 proxy 实现 this 功能 81 | 82 | :star2: 可以在 render 函数中获取 setup 返回的对象 83 | 84 | :star2: 基础插槽支持 85 | 86 | :star2: 具名插槽支持 87 | 88 | :star2: 作用域插槽支持 89 | 90 | :star2: nextTick 的实现 91 | 92 | :star2: 支持 getCurrentInstance API 93 | 94 | :star2: 支持 provide/inject 95 | 96 | :star2: 支持 Text 类型节点 97 | 98 |   99 | 100 | ## src/runtime-dom DOM 平台渲染器 101 | 102 | :star2: 支持自定义渲染器 103 | 104 |   105 | 106 | ## src/compiler-core 编译器 107 | 108 | :star2: 编译插值语法 109 | 110 | :star2: 编译 element 元素 111 | 112 | :star2: 编译 text 文本 113 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['@babel/preset-env', {targets: {node: 'current'}}], 4 | '@babel/preset-typescript', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "micro-vue-next", 3 | "version": "1.0.0", 4 | "main": "lib/vue-next.cjs.js", 5 | "module": "lib/vue-next.esm.js", 6 | "repository": "https://github.com/wumanho/micro-vue-next.git", 7 | "author": "WUMANHO ", 8 | "license": "MIT", 9 | "scripts": { 10 | "test": "vitest", 11 | "build": "rollup -c rollup.config.js" 12 | }, 13 | "devDependencies": { 14 | "@babel/core": "^7.17.5", 15 | "@babel/preset-env": "^7.16.11", 16 | "@babel/preset-typescript": "^7.16.7", 17 | "@rollup/plugin-typescript": "^8.3.1", 18 | "rollup": "^2.70.1", 19 | "tslib": "^2.3.1", 20 | "typescript": "^4.5.5", 21 | "vitest": "^0.24.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1 2 | 3 | exports[`codegen > element 1`] = ` 4 | "const { toDisplayString:_toDisplayString, createElementVNode:_createElementVNode } = Vue 5 | return function render(_ctx,_cache){return _createElementVNode(\\"div\\", null, 'hi,' + _toDisplayString(_ctx.message))}" 6 | `; 7 | 8 | exports[`codegen > interpolation 1`] = ` 9 | "const { toDisplayString:_toDisplayString } = Vue 10 | return function render(_ctx,_cache){return _toDisplayString(_ctx.message)}" 11 | `; 12 | 13 | exports[`codegen > string 1`] = `"return function render(_ctx,_cache){return 'hi'}"`; 14 | 15 | exports[`codegen element 1`] = ` 16 | "const { toDisplayString:_toDisplayString, createElementVNode:_createElementVNode } = Vue 17 | return function render(_ctx,_cache){return _createElementVNode(\\"div\\", null, 'hi,' + _toDisplayString(_ctx.message))}" 18 | `; 19 | 20 | exports[`codegen interpolation 1`] = ` 21 | "const { toDisplayString:_toDisplayString } = Vue 22 | return function render(_ctx,_cache){return _toDisplayString(_ctx.message)}" 23 | `; 24 | 25 | exports[`codegen string 1`] = `"return function render(_ctx,_cache){return 'hi'}"`; 26 | -------------------------------------------------------------------------------- /packages/compiler-core/__tests__/codegen.spec.ts: -------------------------------------------------------------------------------- 1 | import {baseParse} from "../src/parse"; 2 | import {generate} from "../src/codegen"; 3 | import {transform} from "../src/transform"; 4 | import {transformExpression} from "../src/transforms/transformExpression"; 5 | import {transformElement} from "../src/transforms/transformElement"; 6 | import {transformText} from "../src/transforms/transformText"; 7 | 8 | describe("codegen", () => { 9 | test("string", () => { 10 | const ast = baseParse("hi") 11 | // 生成 codegen 根 12 | transform(ast) 13 | //暂时不 transform 14 | const {code} = generate(ast) 15 | //将方法进行快照对比 16 | expect(code).toMatchSnapshot() 17 | }) 18 | test("interpolation", () => { 19 | const ast = baseParse("{{message}}") 20 | // 生成 codegen 根 21 | transform(ast, { 22 | nodeTransforms: [transformExpression] 23 | }) 24 | //暂时不 transform 25 | const {code} = generate(ast) 26 | //将方法进行快照对比 27 | expect(code).toMatchSnapshot() 28 | }) 29 | test("element", () => { 30 | const ast: any = baseParse("
hi,{{message}}
") 31 | // 生成 codegen 根 32 | transform(ast, { 33 | nodeTransforms: [transformExpression, transformElement, transformText] 34 | }) 35 | //暂时不 transform 36 | const {code} = generate(ast) 37 | //将方法进行快照对比 38 | expect(code).toMatchSnapshot() 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /packages/compiler-core/__tests__/parse.spec.ts: -------------------------------------------------------------------------------- 1 | import {baseParse} from "../src/parse"; 2 | import {NodeTypes} from "../src/ast"; 3 | 4 | describe('parse', () => { 5 | describe('interpolation', () => { 6 | test('simple interpolation', () => { 7 | // 简单解析器 8 | const ast = baseParse("{{ message }}") 9 | // root 10 | // interpolation:插值 11 | expect(ast.children[0]).toStrictEqual({ 12 | type: NodeTypes.INTERPOLATION, 13 | content: { 14 | type: NodeTypes.SIMPLE_EXPRESSION, 15 | content: "message" 16 | } 17 | }) 18 | }) 19 | }) 20 | describe('element', () => { 21 | test('simple element div', () => { 22 | // 元素解析器 23 | const ast = baseParse("
") 24 | // root 25 | // interpolation:插值 26 | expect(ast.children[0]).toStrictEqual({ 27 | type: NodeTypes.ELEMENT, 28 | tag: "div", 29 | children: [] 30 | }) 31 | }); 32 | }) 33 | describe('text', () => { 34 | test('simple text', () => { 35 | // 文本解析器 36 | const ast = baseParse("hello text") 37 | // root 38 | // interpolation:插值 39 | expect(ast.children[0]).toStrictEqual({ 40 | type: NodeTypes.TEXT, 41 | content: "hello text" 42 | }) 43 | }) 44 | }) 45 | 46 | test("hello world", () => { 47 | const ast = baseParse("
hi,{{message}}
") 48 | expect(ast.children[0]).toStrictEqual({ 49 | type: NodeTypes.ELEMENT, 50 | tag: "div", 51 | children: [ 52 | { 53 | type: NodeTypes.TEXT, 54 | content: "hi," 55 | }, 56 | { 57 | type: NodeTypes.INTERPOLATION, 58 | content: { 59 | type: NodeTypes.SIMPLE_EXPRESSION, 60 | content: "message" 61 | } 62 | }] 63 | }) 64 | }) 65 | 66 | test('nested element', () => { 67 | const ast = baseParse("

hi

hi,{{message}}
") 68 | expect(ast.children[0]).toStrictEqual({ 69 | type: NodeTypes.ELEMENT, 70 | tag: "div", 71 | children: [ 72 | { 73 | type: NodeTypes.ELEMENT, 74 | tag: "p", 75 | children: [{ 76 | type: NodeTypes.TEXT, 77 | content: "hi" 78 | }] 79 | }, 80 | { 81 | type: NodeTypes.TEXT, 82 | content: "hi," 83 | }, 84 | { 85 | type: NodeTypes.INTERPOLATION, 86 | content: { 87 | type: NodeTypes.SIMPLE_EXPRESSION, 88 | content: "message" 89 | } 90 | }] 91 | }) 92 | }) 93 | 94 | test('should throw error when lack end tag', () => { 95 | expect(() => { 96 | baseParse("
") 97 | }).toThrow(`缺少结束标签:span`) 98 | }) 99 | }) 100 | -------------------------------------------------------------------------------- /packages/compiler-core/__tests__/transform.spec.ts: -------------------------------------------------------------------------------- 1 | import {baseParse} from "../src/parse"; 2 | import {transform} from "../src/transform" 3 | import {NodeTypes} from "../src/ast"; 4 | 5 | describe("transform", () => { 6 | test('happy path', () => { 7 | const ast = baseParse("
hi,{{message}}
") 8 | // 使用插件 9 | const plugin = (node) => { 10 | if (node.type === NodeTypes.TEXT) { 11 | node.content = node.content + "mini-vue" 12 | } 13 | } 14 | // 传入插件 15 | transform(ast, { 16 | nodeTransforms: [plugin] 17 | }) 18 | const nodeText = ast.children[0].children[0] 19 | expect(nodeText.content).toBe("hi,mini-vue") 20 | }); 21 | }) 22 | -------------------------------------------------------------------------------- /packages/compiler-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@micro-vue-next/compiler-core", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@micro-vue-next/shared": "workspace:^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/compiler-core/src/ast.ts: -------------------------------------------------------------------------------- 1 | import {CREATE_ELEMENT_VNODE} from "./runtimeHelpers"; 2 | 3 | export const enum NodeTypes { 4 | INTERPOLATION, 5 | SIMPLE_EXPRESSION, 6 | ELEMENT, 7 | TEXT, 8 | ROOT, 9 | COMPOUND_EXPRESSION 10 | } 11 | 12 | export function createVNodeCall(context,tag, props, children) { 13 | context.helper(CREATE_ELEMENT_VNODE) 14 | return { 15 | type: NodeTypes.ELEMENT, 16 | tag, 17 | props, 18 | children 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/compiler-core/src/codegen.ts: -------------------------------------------------------------------------------- 1 | import {NodeTypes} from "./ast"; 2 | import {CREATE_ELEMENT_VNODE, helperMapName, TO_DISPLAY_STRING} from "./runtimeHelpers"; 3 | import {isString} from "@micro-vue-next/shared"; 4 | 5 | export function generate(ast) { 6 | const context = createCodegenContext() 7 | const {push} = context 8 | // 构造导入语句 9 | genFunctionPreamble(ast, context); 10 | /*----------------------------------------*/ 11 | const functionName = "render" // 函数名 12 | const args = ["_ctx", "_cache"] // 参数数组 13 | const signature = args.join(",") // 参数数组转成 string 14 | // 拼接 15 | push(`function ${functionName}(${signature}){`) 16 | push("return ") 17 | genNode(ast.codegenNode, context) 18 | push("}") 19 | 20 | return { 21 | code: context.code 22 | } 23 | } 24 | 25 | function genCompoundExpression(node, context) { 26 | const children = node.children 27 | const {push} = context 28 | for (let i = 0; i < children.length; i++) { 29 | const child = children[i] 30 | if (isString(child)) { 31 | push(child) 32 | } else { 33 | genNode(child, context) 34 | } 35 | } 36 | } 37 | 38 | /** 39 | * 生成关键的方法体 40 | * @param node node 41 | * @param context codegen 上下文对象 42 | */ 43 | function genNode(node, context) { 44 | switch (node.type) { 45 | case NodeTypes.TEXT: 46 | genText(node, context) 47 | break 48 | case NodeTypes.INTERPOLATION: 49 | genInterpolation(node, context) 50 | break 51 | case NodeTypes.SIMPLE_EXPRESSION: 52 | genExpression(node, context) 53 | break 54 | case NodeTypes.ELEMENT: 55 | genElement(node, context) 56 | break 57 | case NodeTypes.COMPOUND_EXPRESSION: 58 | genCompoundExpression(node, context) 59 | break 60 | } 61 | } 62 | 63 | 64 | function createCodegenContext() { 65 | const context = { 66 | code: '', 67 | push(source) { 68 | context.code += source 69 | }, 70 | helper(key) { 71 | return `_${helperMapName[key]}` 72 | } 73 | } 74 | return context 75 | } 76 | 77 | function genFunctionPreamble(ast, context) { 78 | const {push} = context 79 | const VueBinging = "Vue" 80 | const aliasHelper = (s) => `${helperMapName[s]}:_${helperMapName[s]}` 81 | if (ast.helpers.length > 0) { 82 | push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = ${VueBinging}`) 83 | push("\n") 84 | } 85 | push("return ") 86 | } 87 | 88 | function genText(node, context) { 89 | const {push} = context 90 | push(`'${node.content}'`) 91 | } 92 | 93 | function genInterpolation(node, context) { 94 | const {push, helper} = context 95 | push(`${helper(TO_DISPLAY_STRING)}(`) 96 | genNode(node.content, context) 97 | push(")") 98 | } 99 | 100 | function genExpression(node, context) { 101 | const {push} = context 102 | push(`${node.content}`) 103 | } 104 | 105 | function genElement(node, context) { 106 | const {push, helper} = context 107 | const {tag, children, props} = node 108 | push(`${helper(CREATE_ELEMENT_VNODE)}(`) 109 | genNodeList(genNullable([tag, props, children]), context) 110 | push(")") 111 | } 112 | 113 | function genNodeList(nodes, context) { 114 | const {push} = context 115 | for (let i = 0; i < nodes.length; i++) { 116 | const node = nodes[i] 117 | if (isString(node)) { 118 | push(node) 119 | } else { 120 | genNode(node, context) 121 | } 122 | if (i < node.length - 1) { 123 | push(", ") 124 | } 125 | } 126 | } 127 | 128 | // false 值一律转换成 null 129 | function genNullable(args: any[]) { 130 | return args.map((arg) => arg || "null") 131 | } 132 | -------------------------------------------------------------------------------- /packages/compiler-core/src/compile.ts: -------------------------------------------------------------------------------- 1 | import {baseParse} from "./parse"; 2 | import {transform} from "./transform"; 3 | import {transformExpression} from "./transforms/transformExpression"; 4 | import {transformElement} from "./transforms/transformElement"; 5 | import {transformText} from "./transforms/transformText"; 6 | import {generate} from "./codegen"; 7 | 8 | export function baseCompile(template) { 9 | const ast: any = baseParse(template) 10 | // 生成 codegen 根 11 | transform(ast, { 12 | nodeTransforms: [transformExpression, transformElement, transformText] 13 | }) 14 | return generate(ast) 15 | } 16 | -------------------------------------------------------------------------------- /packages/compiler-core/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./compile" 2 | -------------------------------------------------------------------------------- /packages/compiler-core/src/parse.ts: -------------------------------------------------------------------------------- 1 | import {NodeTypes} from "./ast"; 2 | 3 | const enum TagType { 4 | START, 5 | END 6 | } 7 | 8 | export function baseParse(content: string) { 9 | // 根据 content 创建全局上下文对象 10 | const context = createParserContext(content) 11 | // 创建根 12 | return createRoot(parseChildren(context, [])) 13 | } 14 | 15 | 16 | /** 17 | * 用于创建全局上下文对象 18 | * @param content 原始内容 : {{message}} 19 | */ 20 | function createParserContext(content: string) { 21 | return { 22 | source: content 23 | } 24 | } 25 | 26 | 27 | function createRoot(children) { 28 | return { 29 | children, 30 | type: NodeTypes.ROOT 31 | } 32 | } 33 | 34 | /** 35 | * 该方法循环解析 Children 节点,直到循环条件结束 36 | * @param context 37 | * @param ancestors 栈,记录所有元素 38 | */ 39 | function parseChildren(context, ancestors) { 40 | const nodes: any[] = [] 41 | // 循环解析,直到碰到结束条件 42 | while (!isEnd(context, ancestors)) { 43 | let node 44 | const s = context.source 45 | if (s.startsWith("{{")) { 46 | // 解析插值 47 | node = parseInterpolation(context) 48 | } else if (s[0] === "<") { 49 | // 元素解析,判断尖括号后是否字母a-z,忽略大小写 50 | if (/[a-z]/i.test(s[1])) { 51 | node = parseElement(context, ancestors) 52 | } 53 | } 54 | // 不是插值,不是元素,默认为 text 55 | if (!node) { 56 | node = parseText(context) 57 | } 58 | nodes.push(node) 59 | } 60 | return nodes 61 | } 62 | 63 | 64 | /** 65 | * 解析插值方法 66 | * @param context 全局上下文 67 | */ 68 | function parseInterpolation(context) { 69 | // 定义初始分隔符和结束分隔符 70 | const openDelimiter = "{{" 71 | const closeDelimiter = "}}" 72 | 73 | // 取得 }} 的索引值, 74 | // 第二个参数:开始计算的地方,所以传值为初始分隔符的长度 75 | const closeIndex = context.source.indexOf(closeDelimiter, openDelimiter.length) 76 | // 去掉 {{ 77 | advanceBy(context, openDelimiter.length) 78 | // 获取插值内容长度 79 | const rawContentLength = closeIndex - openDelimiter.length 80 | // 确认实际内容 81 | const rawContent = parseTextData(context, rawContentLength) 82 | const content = rawContent.trim() 83 | // 清空上下文的 source 84 | advanceBy(context, closeDelimiter.length) 85 | return { 86 | type: NodeTypes.INTERPOLATION, 87 | content: { 88 | type: NodeTypes.SIMPLE_EXPRESSION, 89 | content: content, 90 | } 91 | } 92 | } 93 | 94 | /** 95 | * 解析 element 方法 96 | * @param context 全局上下文 97 | * @param ancestors 栈,记录所有元素 98 | */ 99 | function parseElement(context, ancestors) { 100 | const element = parseTag(context, TagType.START) as any; 101 | // 记录解析好的标签 102 | ancestors.push(element) 103 | element.children = parseChildren(context, ancestors) 104 | // 当前标签内的子元素已经解析完之后,弹出元素 105 | ancestors.pop() 106 | // 判断是否有闭合标签 107 | if (startsWithEndTagOpen(context.source, element.tag)) { 108 | // 这一步是清除闭合的那个标签 109 | parseTag(context, TagType.END) 110 | } else { 111 | throw new Error(`缺少结束标签:${element.tag}`) 112 | } 113 | return element 114 | } 115 | 116 | /** 117 | * 用于切割内容 118 | * @param context 上下文: {{message}} 119 | * @param length 切割的长度 120 | */ 121 | function advanceBy(context: any, length: number) { 122 | context.source = context.source.slice(length) 123 | } 124 | 125 | 126 | function parseTag(context, type: number) { 127 | //1.解析 tag 128 | const match: any = /^<\/?([a-z]*)/i.exec(context.source) 129 | const tag = match[1] 130 | //2.清除 source 131 | advanceBy(context, match[0].length) // > 132 | advanceBy(context, 1) // 133 | if (type === TagType.END) return 134 | return { 135 | type: NodeTypes.ELEMENT, 136 | tag 137 | } 138 | } 139 | 140 | 141 | /** 142 | * 获取插值文本和获取文件的方法抽取 143 | * @param context 全局上下文 144 | * @param length 截取长度 145 | */ 146 | function parseTextData(context, length) { 147 | //1.获取文本内容 148 | const content = context.source.slice(0, length) 149 | //2.清空上下文 150 | advanceBy(context, length) 151 | return content; 152 | } 153 | 154 | /** 155 | * 解析文本 方法 156 | * @param context 全局上下文 157 | */ 158 | function parseText(context) { 159 | let endIndex = context.source.length 160 | // 遇到插值表达式或者闭合标签就结束,记录结束位置的索引 161 | let endToken = ["<", "{{"] 162 | for (let i = 0; i < endToken.length; i++) { 163 | const index = context.source.indexOf(endToken[i]) 164 | // 如果同时存在多个结束标记,取靠左边的那个才是正确的 165 | if (index !== -1 && index < endIndex) { 166 | endIndex = index 167 | } 168 | } 169 | // content 就是 text 文本内容 170 | const content = parseTextData(context, endIndex); 171 | return { 172 | type: NodeTypes.TEXT, 173 | content: content 174 | } 175 | } 176 | 177 | /** 178 | * 用于判断是否结束 parse 循环 179 | * @param context 全局上下文 180 | * @param ancestors 栈,记录了所有元素标签 181 | */ 182 | function isEnd(context, ancestors) { 183 | const s = context.source 184 | // 判断是否有对应的闭合标签 185 | if (s.startsWith("= 0; i--) { 187 | const tag = ancestors[i].tag 188 | if (startsWithEndTagOpen(s, tag)) { 189 | //结束条件2:遇到结束标签 190 | return true 191 | } 192 | } 193 | } 194 | //结束条件1:source 没有值 195 | return !s 196 | } 197 | 198 | /** 199 | * 判断是否有闭合标签 200 | */ 201 | function startsWithEndTagOpen(source, tag) { 202 | return source.startsWith(" { 7 | //tag 8 | const vnodeTag = `"${node.tag}"` 9 | //props 10 | let vnodeProps 11 | 12 | //children 13 | const children = node.children 14 | let vnodeChildren = children[0] 15 | const child = children[0] 16 | node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/compiler-core/src/transforms/transformExpression.ts: -------------------------------------------------------------------------------- 1 | import {NodeTypes} from "../ast"; 2 | 3 | export function transformExpression(node) { 4 | if (node.type === NodeTypes.INTERPOLATION) { 5 | node.content = processExpression(node.content) 6 | } 7 | } 8 | 9 | function processExpression(node) { 10 | node.content = "_ctx." + node.content 11 | return node 12 | } 13 | -------------------------------------------------------------------------------- /packages/compiler-core/src/transforms/transformText.ts: -------------------------------------------------------------------------------- 1 | import {NodeTypes} from "../ast"; 2 | import {isText} from "../utils"; 3 | 4 | /** 5 | * 判断 element 节点中的子节点是否为复合类型 6 | * @param node 7 | */ 8 | export function transformText(node) { 9 | if (node.type === NodeTypes.ELEMENT) { 10 | return () => { 11 | // 判断是否复合类型 12 | const {children} = node 13 | let currentContainer 14 | for (let i = 0; i < children.length; i++) { 15 | const child = children[i] 16 | if (isText(child)) { 17 | // 第二层 for 循环,找到下一个节点 18 | for (let j = i + 1; j < children.length; j++) { 19 | const next = children[j] 20 | // 进了这里就证明是复合节点了 21 | if (isText(next)) { 22 | // 初始化 23 | if (!currentContainer) { 24 | currentContainer = children[i] = { 25 | type: NodeTypes.COMPOUND_EXPRESSION, 26 | children: [child] 27 | } 28 | } 29 | // 每个其他节点通过 + 分割 30 | currentContainer.children.push(" + ") 31 | // 把其他节点 push 进去 32 | currentContainer.children.push(next) 33 | // 删除,并校正 j 索引 34 | children.splice(j, 1) 35 | j-- 36 | } else { 37 | currentContainer = undefined 38 | break 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/compiler-core/src/utils.ts: -------------------------------------------------------------------------------- 1 | import {NodeTypes} from "./ast"; 2 | 3 | export function isText(node) { 4 | return node.type === NodeTypes.TEXT || node.type === NodeTypes.INTERPOLATION 5 | } 6 | -------------------------------------------------------------------------------- /packages/reactivity/__tests__/computed.spec.ts: -------------------------------------------------------------------------------- 1 | import {reactive} from "../src"; 2 | import {computed} from "../src/computed"; 3 | import {vi} from 'vitest' 4 | 5 | describe("computed", () => { 6 | it("happy path", () => { 7 | const user = reactive({ 8 | age: 1, 9 | }) 10 | const age = computed(() => { 11 | return user.age 12 | }) 13 | expect(age.value).toBe(1) 14 | }) 15 | it('should compute lazily', function () { 16 | const value = reactive({ 17 | foo: 1, 18 | }) 19 | const getter = vi.fn(() => value.foo) 20 | const cValue = computed(getter) 21 | // lazy 22 | expect(getter).not.toHaveBeenCalled() 23 | //只有调用.value,进入到 get 方法时,才会被调用一次 24 | expect(cValue.value).toBe(1) 25 | expect(getter).toHaveBeenCalledTimes(1) 26 | //值没有更改时 27 | cValue.value 28 | expect(getter).toHaveBeenCalledTimes(1) 29 | // 虽然设置了新的值,但只要没有 .value,都不会重新计算 30 | value.foo = 2 31 | expect(getter).toHaveBeenCalledTimes(1) 32 | // 这时候 getter 才会被调用 33 | expect(cValue.value).toBe(2) 34 | expect(getter).toHaveBeenCalledTimes(2) 35 | // 再次获取 .value,getter 不会重新计算 36 | cValue.value 37 | expect(getter).toHaveBeenCalledTimes(2) 38 | }); 39 | // it('should trigger effect', () => { 40 | // const value = reactive({foo:undefined}) 41 | // const cValue = computed(() => value.foo) 42 | // let dummy 43 | // effect(() => { 44 | // dummy = cValue.value 45 | // }) 46 | // expect(dummy).toBe(undefined) 47 | // value.foo = 1 48 | // expect(dummy).toBe(1) 49 | // }) 50 | }) 51 | -------------------------------------------------------------------------------- /packages/reactivity/__tests__/effect.spec.ts: -------------------------------------------------------------------------------- 1 | import {reactive} from "../src/reactive"; 2 | import {effect, stop} from "../src/effect"; 3 | import {vi} from 'vitest' 4 | 5 | describe('effect', () => { 6 | it('happy path', () => { 7 | const user = reactive({ 8 | age: 10, 9 | name: 'hi' 10 | }) 11 | let nextAge; 12 | effect(() => { 13 | nextAge = user.age + 1 14 | }) 15 | expect(nextAge).toBe(11) 16 | //update 17 | user.age += 1 18 | user.name = "test" 19 | expect(nextAge).toBe(12) 20 | expect(user.name).toBe("test") 21 | }) 22 | 23 | it('should return runner when call effect', () => { 24 | let foo = 10 25 | const runner = effect(() => { 26 | foo += 1 27 | return 'foo' 28 | }) 29 | expect(foo).toBe(11) 30 | const r = runner() 31 | expect(foo).toBe(12) 32 | expect(r).toBe('foo') 33 | }); 34 | it('scheduler', () => { 35 | let dummy 36 | let run: any 37 | const scheduler = vi.fn(() => { 38 | run = runner 39 | }) 40 | const obj = reactive({foo: 1}) 41 | const runner = effect( 42 | () => { 43 | dummy = obj.foo 44 | }, 45 | {scheduler} 46 | ) 47 | expect(scheduler).not.toHaveBeenCalled() 48 | expect(dummy).toBe(1) 49 | //第一个trigger时,scheduler才会被调用 50 | obj.foo++ 51 | expect(scheduler).toHaveBeenCalledTimes(1) 52 | //不会触发更新 53 | expect(dummy).toBe(1) 54 | //手动 run 55 | run() 56 | //更新了 57 | expect(dummy).toBe(2) 58 | }); 59 | it('stop', () => { 60 | let dummy 61 | const obj = reactive({prop: 1}) 62 | const runner = effect(() => { 63 | dummy = obj.prop 64 | }) 65 | obj.prop = 2 66 | expect(dummy).toBe(2) 67 | stop(runner) 68 | //trigger失效 69 | // obj.prop = 3 70 | obj.prop++ 71 | expect(dummy).toBe(2) 72 | //即使stop了,还是可以手动调用 73 | runner() 74 | expect(dummy).toBe(3) 75 | }); 76 | it('onStop', () => { 77 | const obj = reactive({ 78 | foo: 1 79 | }) 80 | const onStop = vi.fn() 81 | let dummy 82 | const runner = effect(() => { 83 | dummy = obj.foo 84 | }, {onStop}) 85 | stop(runner) 86 | expect(onStop).toBeCalledTimes(1) 87 | }); 88 | }) 89 | -------------------------------------------------------------------------------- /packages/reactivity/__tests__/reactive.spec.ts: -------------------------------------------------------------------------------- 1 | import {isReactive, reactive,isProxy} from "../src/reactive"; 2 | 3 | describe('reactive', () => { 4 | it('happy path', () => { 5 | const original = {foo: 1} 6 | const observed = reactive(original) 7 | //observed一定不等于original 8 | expect(observed).not.toBe(original) 9 | expect(observed.foo).toBe(1) 10 | expect(isReactive(observed)).toBe(true) 11 | expect(isReactive(original)).toBe(false) 12 | expect(isProxy(original)).toBe(false) 13 | }) 14 | it("nested reactive", () => { 15 | const original = { 16 | nested: {foo: 1}, 17 | array: [{bar: 2}] 18 | } 19 | const observed = reactive(original) 20 | expect(isReactive(observed.nested)).toBe(true) 21 | expect(isReactive(observed.array)).toBe(true) 22 | expect(isReactive(observed.array[0])).toBe(true) 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/reactivity/__tests__/readonly.spec.ts: -------------------------------------------------------------------------------- 1 | import {isReadonly, readonly, isProxy} from "../src"; 2 | import {vi} from 'vitest' 3 | 4 | describe("readonly", () => { 5 | it("should be readonly", () => { 6 | const original = {foo: 1, bar: {baz: 2}} 7 | const wrapped = readonly(original) 8 | expect(wrapped).not.toBe(original) 9 | expect(isReadonly(wrapped)).toBe(true) 10 | expect(isReadonly(wrapped.bar)).toBe(true) 11 | expect(isProxy(wrapped)).toBe(true) 12 | expect(wrapped.foo).toBe(1) 13 | }) 14 | it('should throw a warning when call set as realonly', () => { 15 | console.warn = vi.fn() 16 | const user = readonly({ 17 | age: 10 18 | }) 19 | user.age = 11 20 | expect(console.warn).toHaveBeenCalled() 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/reactivity/__tests__/ref.spec.ts: -------------------------------------------------------------------------------- 1 | import {effect} from "../src/effect"; 2 | import {ref, isRef, unRef,proxyRef} from "../src/ref" 3 | import {reactive} from "../src/reactive"; 4 | 5 | describe("ref", () => { 6 | it("happy path", () => { 7 | const a = ref(1) 8 | expect(a.value).toBe(1) 9 | }) 10 | it("should be reactive", () => { 11 | const a = ref(1) 12 | let dummy 13 | let calls = 0 14 | effect(() => { 15 | calls += 1 16 | dummy = a.value 17 | }) 18 | expect(calls).toBe(1) 19 | expect(dummy).toBe(1) 20 | a.value = 2 21 | expect(calls).toBe(2) 22 | expect(dummy).toBe(2) 23 | // value 不变的话,不走 trigger 24 | a.value = 2 25 | expect(calls).toBe(2) 26 | expect(dummy).toBe(2) 27 | }) 28 | it("should make nested properties reactive", () => { 29 | const a = ref({ 30 | count: 1 31 | }) 32 | let dummy 33 | effect(() => { 34 | dummy = a.value.count 35 | }) 36 | expect(dummy).toBe(1) 37 | a.value.count = 2 38 | expect(dummy).toBe(2) 39 | 40 | }) 41 | it('isRef', function () { 42 | const a = ref(1) 43 | const user = reactive({ 44 | age:1 45 | }) 46 | expect(isRef(a)).toBe(true) 47 | expect(isRef(1)).toBe(false) 48 | expect(isRef(user)).toBe(false) 49 | }); 50 | it('unRef', function () { 51 | const a = ref(1) 52 | expect(unRef(a)).toBe(1) 53 | expect(unRef(1)).toBe(1) 54 | }); 55 | it('proxyRef', function () { 56 | const user = { 57 | age:ref(10), 58 | name:"xiaohong" 59 | } 60 | const proxyUser = proxyRef(user) 61 | expect(user.age.value).toBe(10) 62 | expect(proxyUser.age).toBe(10) 63 | expect(proxyUser.name).toBe("xiaohong") 64 | proxyUser.age = 20 65 | expect(proxyUser.age).toBe(20) 66 | expect(user.age.value).toBe(20) 67 | proxyUser.age = ref(20) 68 | expect(proxyUser.age).toBe(20) 69 | expect(user.age.value).toBe(20) 70 | }); 71 | }) 72 | -------------------------------------------------------------------------------- /packages/reactivity/__tests__/shallowReadonly.spec.ts: -------------------------------------------------------------------------------- 1 | import {isReadonly, readonly, shallowReadonly} from "../src/reactive"; 2 | import {vi} from 'vitest' 3 | describe("shallowReadonly", () => { 4 | test("should not make non-reactive properties reactive", () => { 5 | const props = shallowReadonly({n: {foo: 1}}) 6 | expect(isReadonly(props)).toBe(true) 7 | expect(isReadonly(props.n)).toBe(false) 8 | }) 9 | it('should throw a warning when call set as realonly', () => { 10 | console.warn = vi.fn() 11 | const user = shallowReadonly({ 12 | age: 10 13 | }) 14 | user.age = 11 15 | expect(console.warn).toHaveBeenCalled() 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /packages/reactivity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@micro-vue-next/reactivity", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@micro-vue-next/shared": "workspace:^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/reactivity/src/baseHandler.ts: -------------------------------------------------------------------------------- 1 | import {track, trigger} from "./effect"; 2 | import {reactive, ReactiveFlag, readonly} from "./reactive"; 3 | import {extend, isObject} from "@micro-vue-next/shared"; 4 | 5 | //get 和 set 只需要初始化一次即可 6 | const defaultGet = createGetter(false) 7 | const defaultSet = createSetter() 8 | const readOnlyGet = createGetter(true) 9 | const shallowReadonlyGet = createGetter(true, true) 10 | 11 | function createGetter(isReadonly: boolean, shallow: boolean = false) { 12 | return function (target, key) { 13 | //实现 isReactive 方法 14 | if (key === ReactiveFlag.IS_REACTIVE) { 15 | return !isReadonly 16 | } else if (key === ReactiveFlag.IS_READONLY) { 17 | return isReadonly 18 | } 19 | //target = 原始对象raw,key就是用户访问的那个key 20 | const res = Reflect.get(target, key) 21 | if (shallow) { 22 | return res 23 | } 24 | //如果是 object 的话,将返回的对象也设置为代理 25 | if (isObject(res)) { 26 | return isReadonly ? readonly(res) : reactive(res) 27 | } 28 | if (!isReadonly) { 29 | //依赖收集 30 | track(target, key) 31 | } 32 | return res 33 | } 34 | } 35 | 36 | function createSetter() { 37 | return function (target, key, value) { 38 | //set的时候需要触发收集的依赖 39 | const res = Reflect.set(target, key, value) 40 | //触发副作用函数 41 | trigger(target, key) 42 | //最后当然是要做set该做的事 43 | return res 44 | } 45 | } 46 | 47 | export const mutableHandlers = { 48 | get: defaultGet, 49 | set: defaultSet 50 | } 51 | 52 | export const readonlyHandlers = { 53 | get: readOnlyGet, 54 | set(target, key, value) { 55 | console.warn('readonly') 56 | return true 57 | } 58 | } 59 | 60 | export const shallowReadonlyHandlers = extend({}, readonlyHandlers, { 61 | get: shallowReadonlyGet 62 | }) 63 | -------------------------------------------------------------------------------- /packages/reactivity/src/computed.ts: -------------------------------------------------------------------------------- 1 | import {ReactiveEffect} from "./effect"; 2 | 3 | class ComputedRefImpl { 4 | private readonly getter: () => any; 5 | private _dirty: boolean = true; //是否刷新缓存 6 | private _value: any 7 | private _effect: any 8 | 9 | constructor(getter) { 10 | this.getter = getter; 11 | this._effect = new ReactiveEffect(getter, () => { 12 | // trigger 时解除锁,除了解开锁之外什么也不做 13 | if (!this._dirty) { 14 | this._dirty = true 15 | } 16 | }) 17 | } 18 | 19 | get value() { 20 | if (this._dirty) { 21 | this._dirty = false 22 | //记录 value,控制是否返回 & 这里会进入 track 流程 23 | this._value = this._effect.run(); 24 | } 25 | //这个就是缓存的值,因为每次调用都会返回它 26 | return this._value 27 | } 28 | } 29 | 30 | export function computed(getter) { 31 | return new ComputedRefImpl(getter) 32 | } -------------------------------------------------------------------------------- /packages/reactivity/src/effect.ts: -------------------------------------------------------------------------------- 1 | import {extend} from "@micro-vue-next/shared"; 2 | 3 | //全局容器,用于保存当前的effect方法 4 | let activeEffect: any 5 | let shouldTrack: boolean 6 | 7 | export class ReactiveEffect { 8 | private readonly _fn: any 9 | public scheduler: Function | undefined 10 | deps = [] 11 | active = true 12 | onStop?: () => void 13 | 14 | constructor(fn, scheduler?: Function) { 15 | this._fn = fn 16 | this.scheduler = scheduler 17 | } 18 | 19 | run() { 20 | activeEffect = this 21 | if (!this.active) { 22 | return this._fn() 23 | } 24 | //如果不是stop状态,就要维护一下shouldTrack开关 25 | shouldTrack = true 26 | const result = this._fn() 27 | shouldTrack = false 28 | return result 29 | } 30 | 31 | stop() { 32 | // stop()会清除所有effect 33 | // 所以只要清空过一次,就可以将 active 设置为 false 了 34 | if (this.active) { 35 | cleanUpEffect(this) 36 | //onStop回调 37 | if (this.onStop) { 38 | this.onStop() 39 | } 40 | this.active = false 41 | } 42 | } 43 | } 44 | 45 | function cleanUpEffect(effect) { 46 | effect.deps.forEach((dep: any) => { 47 | dep.delete(effect) 48 | }) 49 | effect.deps.length = 0 50 | } 51 | 52 | //语义化方法抽取 53 | export function isTracking(): boolean { 54 | return shouldTrack && activeEffect !== undefined 55 | } 56 | 57 | // Map 58 | let targetMap = new Map() 59 | 60 | export function track(target, key) { 61 | //如果shouldTrack为false的话,就不应该再走收集依赖 62 | if (!isTracking()) return 63 | //依赖收集的对应关系 target -> keys -> dep 64 | let depsMap = targetMap.get(target) 65 | //处理初始化 66 | if (!depsMap) { 67 | depsMap = new Map() 68 | targetMap.set(target, depsMap) 69 | } 70 | let dep = depsMap.get(key) 71 | if (!dep) { 72 | dep = new Set() 73 | depsMap.set(key, dep) 74 | } 75 | trackEffects(dep) 76 | } 77 | 78 | //抽取依赖收集的方法,与ref公用 79 | export function trackEffects(dep) { 80 | //不再重复收集 81 | if (dep.has(activeEffect)) return 82 | dep.add(activeEffect) 83 | activeEffect.deps.push(dep) 84 | } 85 | 86 | export function trigger(target, key) { 87 | //根据target -> key 可以获取到 dep 对象 88 | //遍历执行 dep 对象中所有收集到的副作用函数 89 | let depsMap = targetMap.get(target) 90 | let dep = depsMap.get(key) 91 | if (dep) { 92 | triggerEffects(dep) 93 | } 94 | } 95 | 96 | //抽取trigger方法,与ref公用 97 | export function triggerEffects(dep) { 98 | for (const effect of dep) { 99 | if (effect.scheduler) { 100 | effect.scheduler() 101 | } else { 102 | effect.run() 103 | } 104 | } 105 | } 106 | 107 | export function effect(fn, options?: any) { 108 | // const {scheduler} = options 109 | const _effect = new ReactiveEffect(fn) 110 | //将 options 直接挂载到_effect 111 | if (options) { 112 | extend(_effect, options) 113 | } 114 | //将effect收集的依赖封装到 reactiveeffect 类的run方法中 115 | _effect.run() 116 | const runner: any = _effect.run.bind(_effect) 117 | runner.effect = _effect 118 | return runner 119 | } 120 | 121 | export function stop(runner) { 122 | runner.effect.stop() 123 | } 124 | -------------------------------------------------------------------------------- /packages/reactivity/src/index.ts: -------------------------------------------------------------------------------- 1 | export {ref, proxyRef, isRef, unRef} from "./ref" 2 | export {reactive, readonly, shallowReadonly, isReactive, isReadonly, isProxy} from './reactive' 3 | export {effect} from './effect' 4 | -------------------------------------------------------------------------------- /packages/reactivity/src/reactive.ts: -------------------------------------------------------------------------------- 1 | import {mutableHandlers, readonlyHandlers, shallowReadonlyHandlers} from "./baseHandler"; 2 | import {isObject} from "@micro-vue-next/shared"; 3 | 4 | export const enum ReactiveFlag { 5 | IS_REACTIVE = "__v_isReactive", 6 | IS_READONLY = "__v_isReadonly" 7 | } 8 | 9 | export function reactive(raw) { 10 | return createActiveObject(raw, mutableHandlers) 11 | } 12 | 13 | export function shallowReadonly(raw) { 14 | return createActiveObject(raw, shallowReadonlyHandlers) 15 | } 16 | 17 | export function readonly(raw) { 18 | return createActiveObject(raw, readonlyHandlers) 19 | } 20 | 21 | function createActiveObject(raw: any, baseHandlers) { 22 | if(!isObject(raw)){ 23 | console.warn("create proxy failed, target much be an Object!") 24 | return 25 | } 26 | return new Proxy(raw, baseHandlers) 27 | } 28 | 29 | export function isReactive(value) { 30 | return !!value[ReactiveFlag.IS_REACTIVE] 31 | } 32 | 33 | export function isReadonly(value) { 34 | return !!value[ReactiveFlag.IS_READONLY] 35 | } 36 | 37 | export function isProxy(value) { 38 | return isReactive(value) || isReadonly(value) 39 | } 40 | -------------------------------------------------------------------------------- /packages/reactivity/src/ref.ts: -------------------------------------------------------------------------------- 1 | import {trackEffects, triggerEffects, isTracking} from "./effect"; 2 | import {hasChanged, isObject} from "@micro-vue-next/shared"; 3 | import {reactive} from "./reactive"; 4 | 5 | class RefImpl { 6 | private _value: any 7 | private _rawValue: any 8 | public deps 9 | public __v_isRef: boolean 10 | 11 | constructor(value) { 12 | this._rawValue = value 13 | this.__v_isRef = true 14 | //如果 value 是个对象的话,则需要用 reactive 包裹 15 | this._value = convert(value) 16 | this.deps = new Set() 17 | } 18 | 19 | //收集依赖 20 | get value() { 21 | trackRefValue(this) 22 | return this._value 23 | } 24 | 25 | //触发依赖 26 | set value(newVal) { 27 | //如果数据没有变更,不触发依赖 28 | if (hasChanged(newVal, this._rawValue)) { 29 | this._rawValue = newVal 30 | this._value = convert(newVal) 31 | triggerEffects(this.deps) 32 | } 33 | } 34 | } 35 | 36 | function trackRefValue(ref) { 37 | if (isTracking()) { 38 | trackEffects(ref.deps) 39 | } 40 | } 41 | 42 | //用于判断是否为对象类型 43 | function convert(value) { 44 | return isObject(value) ? reactive(value) : value 45 | } 46 | 47 | export function ref(value) { 48 | return new RefImpl(value) 49 | } 50 | 51 | export function isRef(ref) { 52 | return !!ref.__v_isRef 53 | } 54 | 55 | export function unRef(ref) { 56 | return isRef(ref) ? ref.value : ref 57 | } 58 | 59 | export function proxyRef(objectWithRefs) { 60 | return new Proxy(objectWithRefs, { 61 | //如果是 ref 就返回.value,不是的话直接返回值即可 62 | get(target, key) { 63 | return unRef(Reflect.get(target, key)) 64 | }, 65 | set(target, key, value) { 66 | //如果访问的key本身是一个ref,但传入的参数又不是一个ref对象,就要将target[key]的value值重新赋值 67 | if (isRef(target[key]) && !isRef(value)) { 68 | return target[key].value = value 69 | } else { 70 | //否则,直接将target[key]替换成新的ref对象即可 71 | return Reflect.set(target, key, value) 72 | } 73 | } 74 | }) 75 | } 76 | 77 | -------------------------------------------------------------------------------- /packages/runtime-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@micro-vue-next/runtime-core", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@micro-vue-next/reactivity": "workspace:^1.0.0", 14 | "@micro-vue-next/shared": "workspace:^1.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/runtime-core/src/apiInject.ts: -------------------------------------------------------------------------------- 1 | import {getCurrentInstance} from "./component"; 2 | 3 | /** 4 | * 负责从父组件中取出对应的键值对 5 | * @param key 键 6 | */ 7 | export function inject(key, defaultValue) { 8 | const currentInstance = getCurrentInstance() as any 9 | if (currentInstance) { 10 | const parentProvides = currentInstance.parent.provides 11 | if (parentProvides[key]) { 12 | return parentProvides[key] 13 | } else if (defaultValue) { //处理默认值 14 | if (typeof defaultValue === "function") { 15 | return defaultValue() 16 | } else { 17 | return defaultValue 18 | } 19 | } 20 | } 21 | } 22 | 23 | /** 24 | * 负责将键值对保存在 component 实例的 provides 对象中 25 | * @param key 键 26 | * @param value 值 27 | */ 28 | export function provide(key, value) { 29 | // 需要获取当前实例,所以要求必须在 setup 中调用 30 | const currentInstance = getCurrentInstance() as any 31 | if (currentInstance) { 32 | let {provides} = currentInstance 33 | const parentProvides = currentInstance.parent.provides 34 | // 仅在初始化的时候进行原型链赋值操作 35 | if (provides === parentProvides) { 36 | // 原型链赋值 37 | provides = currentInstance.provides = Object.create(parentProvides) 38 | } 39 | provides[key] = value 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/runtime-core/src/component.ts: -------------------------------------------------------------------------------- 1 | import {PublicInstanceProxyHandlers} from "./componentPublisInstalce"; 2 | import {initProps} from "./componentProps"; 3 | import {shallowReadonly, proxyRef} from "@micro-vue-next/reactivity"; 4 | import {emit} from "./componentEmit"; 5 | import {initSlots} from "./componentSlots"; 6 | 7 | export function createComponentInstance(vnode, parent) { 8 | const component = { 9 | vnode, 10 | parent, 11 | isMounted: false, // 用于判断组件是否已经初始化 12 | type: vnode.type, //方便获取,如果是组件的话就是 App 对象,如果是元素的话就是标签名 13 | setupState: {}, // setup 返回的数据 14 | props: {}, //组件 props 15 | slots: {}, //组件插槽 16 | provides: parent ? parent.provides : {}, 17 | subTree: {}, // 用于记录旧的组件节点树 18 | next: null, // 存储新的节点树 19 | emit: () => { 20 | } 21 | } 22 | //初始化 componentEmit 23 | component.emit = emit.bind(null, component) as any 24 | return component 25 | } 26 | 27 | export function setupComponent(instance) { 28 | //初始化组件的 props 29 | initProps(instance, instance.vnode.props) 30 | //初始化组件的插槽 31 | initSlots(instance, instance.vnode.children) 32 | //处理有状态的组件(普通组件) 33 | setupStatefulComponent(instance) 34 | } 35 | 36 | function setupStatefulComponent(instance) { 37 | const Component = instance.type 38 | //解构出来 setup 返回的对象 39 | const {setup} = Component 40 | //组件代理对象 ctx,用于绑定到组件的this上,使用户可以通过this来获取到setup返回的内容 41 | instance.proxy = new Proxy({_: instance}, PublicInstanceProxyHandlers) 42 | if (setup) { 43 | //在调用 setup 前,获取当前组件的实例 44 | setCurrentInstance(instance) 45 | //setupResult 可能是 function 或者 object 46 | //传入 props,但props必须是只读的 47 | const setupResult = setup(shallowReadonly(instance.props), { 48 | emit: instance.emit 49 | }) 50 | setCurrentInstance(null) 51 | handleSetupResult(instance, setupResult) 52 | } 53 | } 54 | 55 | function handleSetupResult(instance, setupResult: any) { 56 | //TODO function 57 | if (typeof setupResult === "object") { 58 | //赋值到 instance,使用 proxyRef 包裹,可以不使用.value直接获取值 59 | instance.setupState = proxyRef(setupResult) 60 | } 61 | //给定 render 函数 62 | finishComponentSetup(instance) 63 | } 64 | 65 | let currentInstance = null 66 | 67 | function finishComponentSetup(instance) { 68 | const Component = instance.type 69 | if (compiler && !Component.render) { 70 | if (Component.template) { 71 | Component.render = compiler(Component.template) 72 | } 73 | } 74 | //必须要有 render 函数 75 | instance.render = Component.render 76 | } 77 | 78 | export function getCurrentInstance() { 79 | return currentInstance 80 | } 81 | 82 | function setCurrentInstance(instance) { 83 | currentInstance = instance 84 | } 85 | 86 | let compiler 87 | 88 | export function registerRuntimeCompiler(_compiler) { 89 | compiler = _compiler 90 | } 91 | -------------------------------------------------------------------------------- /packages/runtime-core/src/componentEmit.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * emit 功能 3 | * @param instance 组件实例 4 | * @param event 用户自定义事件名 5 | */ 6 | import {camelize, toHandlerKey} from "@micro-vue-next/shared"; 7 | 8 | export function emit(instance, event, ...args) { 9 | const {props} = instance 10 | 11 | //组装标准自定义事件名 12 | const handlerName: string = toHandlerKey(camelize(event)) 13 | 14 | const handler = props[handlerName] 15 | //执行自定义事件 16 | handler && handler(...args) 17 | } 18 | -------------------------------------------------------------------------------- /packages/runtime-core/src/componentProps.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 初始化组件 props 3 | * @param instance 实例 4 | * @param rawProps 没有处理过的 props 5 | */ 6 | export function initProps(instance, rawProps) { 7 | instance.props = rawProps || {} 8 | } 9 | -------------------------------------------------------------------------------- /packages/runtime-core/src/componentPublisInstalce.ts: -------------------------------------------------------------------------------- 1 | import {hasOwn} from "@micro-vue-next/shared"; 2 | 3 | const publicPropertiesMap = { 4 | $el: (i) => i.vnode.el, 5 | $slots: (i) => i.slots, 6 | $props: (i) => i.props 7 | } 8 | 9 | export const PublicInstanceProxyHandlers = { 10 | get({_: instance}, key) { 11 | //拿到 setupState,和 props 12 | const {setupState, props} = instance 13 | 14 | if (hasOwn(setupState, key)) { 15 | return setupState[key] 16 | } else if (hasOwn(props, key)) { 17 | return props[key] 18 | } 19 | // this.$el 获取根元素 20 | const publicGetter = publicPropertiesMap[key] 21 | if (publicGetter) { 22 | return publicGetter(instance) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/runtime-core/src/componentSlots.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 插槽功能 3 | * @param instance 组件实例 4 | * @param children 组件实例的children 5 | */ 6 | import {ShapeFlags} from "@micro-vue-next/shared"; 7 | 8 | export function initSlots(instance, children) { 9 | //判断是否 slot 10 | const {vnode} = instance 11 | if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { 12 | normalizeObjectSlots(children, instance.slots) 13 | } 14 | } 15 | 16 | 17 | function normalizeObjectSlots(children: any, slots: any) { 18 | //根据 key 获取对应的 slot 19 | for (const key in children) { 20 | const value = children[key] 21 | slots[key] = (props) => normalizeSlotValue(value(props)) 22 | } 23 | } 24 | 25 | // 统一将 slots 包装成数组 26 | function normalizeSlotValue(value) { 27 | return Array.isArray(value) ? value : [value] 28 | } 29 | -------------------------------------------------------------------------------- /packages/runtime-core/src/componentUpdateUtils.ts: -------------------------------------------------------------------------------- 1 | export function shouldUpdateComponent(prevVNode, nextVNode) { 2 | const {props: prevProps} = prevVNode 3 | const {props: nextProps} = nextVNode 4 | for (let key in nextProps) { 5 | if (nextProps[key] !== prevProps[key]) { 6 | return true 7 | } 8 | } 9 | return false 10 | } 11 | -------------------------------------------------------------------------------- /packages/runtime-core/src/createApp.ts: -------------------------------------------------------------------------------- 1 | import {createVNode} from "./vnode"; 2 | 3 | export function createAppAPI(render) { 4 | return function createApp(rootComponent) { 5 | return { 6 | mount(rootContainer) { 7 | //需要先将入口转换成 vnode 8 | //所有操作都基于 vnode 完成 9 | const vnode = createVNode(rootComponent) 10 | render(vnode, rootContainer) 11 | } 12 | } 13 | } 14 | } 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/runtime-core/src/h.ts: -------------------------------------------------------------------------------- 1 | import {createVNode} from "./vnode"; 2 | 3 | export function h(type, props?, children?) { 4 | return createVNode(type, props, children) 5 | } -------------------------------------------------------------------------------- /packages/runtime-core/src/helpers/renderSlots.ts: -------------------------------------------------------------------------------- 1 | import {createVNode, Fragment} from "../vnode"; 2 | 3 | /** 4 | * 由于插槽可能以数组的方式传入(多个元素),封装一个可读性更强的方法来渲染,并兼容非数组的情况 5 | * @param slots 插槽 6 | * @param name 插槽插入的位置 7 | */ 8 | export function renderSlots(slots, name, props) { 9 | const slot = slots[name] 10 | if (slot && typeof slot === "function") { 11 | // Fragment 类型,不需要外层 div 包裹直接渲染子元素 12 | return createVNode(Fragment, {}, slot(props)) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/runtime-core/src/index.ts: -------------------------------------------------------------------------------- 1 | export {h} from './h' 2 | export {createTextVNode,createElementVNode} from './vnode' 3 | export {renderSlots} from "./helpers/renderSlots" 4 | export {getCurrentInstance, registerRuntimeCompiler} from "./component" 5 | export {provide, inject} from "./apiInject" 6 | export {createRenderer} from "./renderer" 7 | export {nextTick} from "./scheduler" 8 | export {toDisplayString} from "@micro-vue-next/shared" 9 | export * from '@micro-vue-next/reactivity' 10 | 11 | -------------------------------------------------------------------------------- /packages/runtime-core/src/renderer.ts: -------------------------------------------------------------------------------- 1 | //render 只干一件事,就是调用 patch 2 | import {createComponentInstance, setupComponent} from "./component"; 3 | import {ShapeFlags} from "@micro-vue-next/shared"; 4 | import {Fragment, Text} from "./vnode" 5 | import {createAppAPI} from "./createApp"; 6 | import {effect} from "@micro-vue-next/reactivity"; 7 | import {EMPTY_OBJ} from "@micro-vue-next/shared"; 8 | import {shouldUpdateComponent} from "./componentUpdateUtils"; 9 | import {queueJobs} from "./scheduler"; 10 | 11 | export function createRenderer(options) { 12 | // 获取自定义渲染器,默认渲染到 Dom 平台 13 | const { 14 | createElement: hostCreateElement, 15 | patchProp: hostPatchProp, 16 | insert: hostInsert, 17 | remove: hostRemove, 18 | setElementText: hostSetElementText 19 | } = options 20 | 21 | function render(vnode, container) { 22 | patch(null, vnode, container, null, null) 23 | } 24 | 25 | /** 26 | * 核心渲染方法,渲染逻辑的入口 27 | * @param n1 旧的节点树,如果不存在,则处于初始化流程,如果存在,则处于更新的流程 28 | * @param n2 新的节点树 29 | * @param container 父元素 30 | * @param parentComponent 父组件 31 | * @param anchor 锚点 32 | */ 33 | function patch(n1, n2, container, parentComponent, anchor) { 34 | //判断 vode 是否 element,element 要单独处理 35 | //element:{type:'div',props:'hello'} 36 | //组件:{ type:APP{render()=>{} ,setup()=>{} }} 37 | const {type, shapeFlag} = n2 38 | switch (type) { 39 | case Fragment: 40 | processFragment(n2, container, parentComponent, anchor) 41 | break 42 | case Text: 43 | processText(n2, container) 44 | break 45 | default: 46 | if (shapeFlag & ShapeFlags.ELEMENT) { 47 | processElement(n1, n2, container, parentComponent, anchor) 48 | } else if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { 49 | processComponent(n1, n2, container, parentComponent, anchor) 50 | } 51 | } 52 | } 53 | 54 | function processText(n2, container) { 55 | // children 就是一个字符串 56 | const {children} = n2 57 | // 创建 text 节点,并赋值到 vnode 的 el 上 58 | const textNode = (n2.el = document.createTextNode(children)) 59 | container.append(textNode) 60 | } 61 | 62 | function processFragment(n2, container, parentComponent, anchor) { 63 | mountChildren(n2.children, container, parentComponent, anchor) 64 | } 65 | 66 | /** 67 | * 处理组件挂载 & 更新逻辑 68 | * @param n1 old 69 | * @param n2 new 70 | * @param container 容器 71 | * @param parentComponent 父组件 72 | * @param anchor 锚点 73 | */ 74 | function processComponent(n1, n2, container, parentComponent, anchor) { 75 | if (!n1) { 76 | //挂载 77 | mountComponent(n2, container, parentComponent, anchor) 78 | } else { 79 | updateComponent(n1, n2) 80 | } 81 | } 82 | 83 | function updateComponent(n1, n2) { 84 | // n2 是更新的实例,没有走初始化,所以需要把 n1 的 component 继承一下 85 | n2.component = n1.component 86 | const instance = n2.component 87 | if (shouldUpdateComponent(n1, n2)) { 88 | // 组件实例的 next 用于存储新的节点树 89 | instance.next = n2 90 | // update() 是 effect 函数返回的 runner 91 | instance.update() 92 | } else { 93 | n2.el = n1.el 94 | n2.vnode = n2 95 | } 96 | } 97 | 98 | /** 99 | * 处理 element,判断是初始化还是更新 100 | * @param n1 老节点树 101 | * @param n2 新节点树 102 | * @param container 父元素 103 | * @param parentComponent 父组件 104 | * @param anchor 锚点 105 | */ 106 | function processElement(n1, n2, container, parentComponent, anchor) { 107 | if (!n1) { 108 | mountElement(n2, container, parentComponent, anchor) 109 | } else { 110 | patchElement(n1, n2, container, parentComponent, anchor) 111 | } 112 | } 113 | 114 | /** 115 | * element 更新处理,包括对属性、Children的更新处理 116 | * @param n1 老节点树 117 | * @param n2 新节点树 118 | * @param container 父元素 119 | * @param parentComponent 父组件 120 | * @param anchor 锚点 121 | */ 122 | function patchElement(n1, n2, container, parentComponent, anchor) { 123 | const oldProps = n1.props || EMPTY_OBJ 124 | const newProps = n2.props || EMPTY_OBJ 125 | // n2 由于没有走初始化的逻辑,所有没有 el 属性 126 | // 所以先将 n1 的 el 赋值给 n2,用于下次更新的时候获取 127 | const el = (n2.el = n1.el) 128 | patchChildren(n1, n2, el, parentComponent, anchor) 129 | patchProp(el, oldProps, newProps) 130 | } 131 | 132 | /** 133 | * 对 children 的更新处理 134 | * @param n1 老节点 135 | * @param n2 新节点 136 | */ 137 | function patchChildren(n1, n2, container, parentComponent, anchor) { 138 | // 获取旧元素的类型和 children 139 | const prevShapeFlag = n1.shapeFlag 140 | const c1 = n1.children 141 | // 新元素的类型以及 children 142 | const shapeFlag = n2.shapeFlag 143 | const c2 = n2.children 144 | // 新元素是 text 普通文本 145 | if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { 146 | // 如果老节点的 children 是数组的话,需要先清空掉 147 | if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) { 148 | // 1.把老节点的children清空 149 | unmountChildren(n1.children) 150 | } 151 | // 再设置新的 text 值 152 | if (c1 !== c2) hostSetElementText(container, c2) 153 | } else { // 新节点的 children 是数组 154 | if (prevShapeFlag & ShapeFlags.TEXT_CHILDREN) { 155 | // 清空老的文本节点 156 | hostSetElementText(container, "") 157 | mountChildren(c2, container, parentComponent, anchor) 158 | } else { 159 | // array diff 160 | patchKeyedChildren(c1, c2, container, parentComponent, anchor) 161 | } 162 | } 163 | } 164 | 165 | function unmountChildren(children) { 166 | for (let i = 0; i < children.length; i++) { 167 | const el = children[i].el 168 | hostRemove(el) 169 | } 170 | } 171 | 172 | /** 173 | * diff 核心逻辑 174 | * @param c1 old children 175 | * @param c2 new children 176 | * @param container 在当前方法中不关键 177 | * @param parentComponent 在当前方法中不关键 178 | * @param parentAnchor 锚点,用于指定元素插入的位置 179 | */ 180 | function patchKeyedChildren(c1, c2, container, parentComponent, parentAnchor) { 181 | let i = 0 // 新节点树游标 182 | let e1 = c1.length - 1 // 索引指向(老)节点树尾部 183 | let e2 = c2.length - 1 // 索引指向(新)节点树尾部 184 | 185 | // 左侧位移 186 | while (i <= e1 && i <= e2) { // 循环条件:游标不能大于等于 e1 和 e2 187 | const n1 = c1[i] // 取得元素(头部) 188 | const n2 = c2[i] // 取得元素(头部) 189 | if (isSameVNodeType(n1, n2)) { 190 | patch(n1, n2, container, parentComponent, parentAnchor) 191 | } else { // 直到出现不同的元素,就没必要再循环下去了 192 | break 193 | } 194 | i++ 195 | } 196 | 197 | // 右侧位移 198 | while (i <= e1 && i <= e2) { // 循环条件:游标不能大于等于 e1 和 e2 199 | const n1 = c1[e1] // 取得元素(尾部) 200 | const n2 = c2[e2] // 取得元素(尾部) 201 | if (isSameVNodeType(n1, n2)) { 202 | patch(n1, n2, container, parentComponent, parentAnchor) 203 | } else { 204 | break 205 | } 206 | e1-- 207 | e2-- 208 | } 209 | 210 | /** 位移完毕,已确定中间部分 **/ 211 | 212 | if (i > e1) { // 新的节点树在原来的基础上新增了节点 213 | if (i <= e2) { 214 | const nextPos = e2 + 1 215 | const anchor = nextPos < c2.length ? c2[nextPos].el : null 216 | // i 大于 e1 小于等于 e2 的部分就是新增的节点 217 | while (i <= e2) { 218 | patch(null, c2[i], container, parentComponent, anchor) 219 | i++ 220 | } 221 | } 222 | } else if (i > e2) { // 新的节点树在原来的基础上少了节点 223 | while (i <= e1) { 224 | hostRemove(c1[i].el) 225 | i++ 226 | } 227 | } else { // 处理中间乱序的情况下的逻辑 228 | let s1 = i // 老节点树的起始索引 229 | let s2 = i // 新节点树的起始索引 230 | 231 | // 用于建立 key -> 元素位置 映射关系 232 | const keyToNewIndexMap = new Map() 233 | // 用于记录新节点树(除去左右两侧)的节点数量,即需要处理的总数量 234 | const toBePatch = e2 - s2 + 1 235 | // 新老映射关系表,为了保证性能,采用了定长数组 236 | const newIndexToOldIndexMap = new Array(toBePatch) 237 | // 标记是否有需要移动的元素 238 | let moved = false 239 | // 用于临时保存元素的索引,也是为了判断是否有需要移动的元素 240 | let maxNewIndexSoFar = 0 241 | 242 | for (let i = 0; i < toBePatch; i++) { 243 | newIndexToOldIndexMap[i] = 0 // 初始化映射表 244 | } 245 | // 用于记录已处理的新节点的数量 246 | let patched = 0 247 | 248 | for (let i = s2; i <= e2; i++) { 249 | const nextChild = c2[i] 250 | keyToNewIndexMap.set(nextChild.key, i) // key -> 元素位置 251 | } 252 | 253 | for (let i = s1; i <= e1; i++) { 254 | const prevChild = c1[i] // 旧节点中间部分的起始元素 255 | 256 | // 已处理的元素已经大于等于需要处理的总元素 257 | if (patched >= toBePatch) { 258 | //剩下的元素全部移除掉,然后过掉当前循环 259 | hostRemove(prevChild.el) 260 | continue 261 | } 262 | 263 | let newIndex 264 | // key 值对比 265 | if (prevChild.key !== null) { 266 | newIndex = keyToNewIndexMap.get(prevChild.key) // 通过 key 尝试从新节点树中获取到相同的元素 267 | } else { 268 | // 没有 key,遍历对比 269 | for (let j = s2; j <= e2; j++) { 270 | if (isSameVNodeType(prevChild, c2[j])) { 271 | newIndex = j 272 | break 273 | } 274 | } 275 | } 276 | 277 | if (newIndex === undefined) { 278 | // 元素没有出现在新的节点树中,移除 279 | hostRemove(prevChild.el) 280 | 281 | } else {// 元素出现在新的节点树中 282 | // 记录当前元素的索引位置,如果元素在新节点树中的位置比原来的位置小了,意味着有元素的移动,需要进行最长递增子序列计算 283 | // 否则就意味着元素位置没有变动,就不需要走下面的逻辑了 284 | if (newIndex >= maxNewIndexSoFar) { 285 | maxNewIndexSoFar = newIndex 286 | } else { 287 | moved = true 288 | } 289 | newIndexToOldIndexMap[newIndex - s2] = i + 1 290 | patch(prevChild, c2[newIndex], container, parentComponent, null) 291 | patched++ 292 | } 293 | } 294 | 295 | // 获取最长递增子序列(即稳定不变的元素) 296 | const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : [] 297 | // 游标 j 指向最长递增子序列 298 | let j = increasingNewIndexSequence.length - 1 299 | // 倒序匹配,确保元素插入到正确的位置 300 | for (let i = toBePatch - 1; i >= 0; i--) { 301 | const nextIndex = i + s2 302 | const nextChild = c2[nextIndex] // 从新节点树中取得元素 303 | const anchor = nextIndex + 1 < c2.length ? c2[nextIndex + 1].el : null // 锚点,不可以大于 c2 的长度 304 | if (newIndexToOldIndexMap[i] === 0) { 305 | // 创建新元素 306 | patch(null, nextChild, container, parentComponent, anchor) 307 | } else if (moved) { 308 | if (j < 0 || i !== increasingNewIndexSequence[j]) { 309 | // 移动元素 310 | console.log("移动位置") 311 | hostInsert(nextChild.el, container, anchor) 312 | } else { 313 | j-- 314 | } 315 | } 316 | } 317 | } 318 | } 319 | 320 | function isSameVNodeType(n1, n2) { 321 | return n1.type === n2.type && n1.key === n2.key 322 | } 323 | 324 | 325 | /** 326 | * 327 | * @param el 328 | * @param oldProp 329 | * @param newProp 330 | */ 331 | function patchProp(el, oldProp, newProp) { 332 | // 判断新节点树的 prop 是否有变化 333 | if (oldProp !== newProp) { 334 | for (const key in newProp) { 335 | // 根据新属性列表的key获取老属性列表对应的值 336 | const prevProp = oldProp[key] 337 | const nextProp = newProp[key] 338 | 339 | if (prevProp !== newProp) { 340 | hostPatchProp(el, key, prevProp, nextProp) 341 | } 342 | } 343 | if (oldProp !== EMPTY_OBJ) { 344 | // 如果老的 prop 在新的节点树里面被删除了,那这个属性也要删除掉 345 | for (const key in oldProp) { 346 | if (!(key in newProp)) { 347 | hostPatchProp(el, key, oldProp[key], null) 348 | } 349 | } 350 | } 351 | } 352 | } 353 | 354 | function mountComponent(initialVNode, container, parentComponent, anchor) { 355 | // 必须先根据虚拟结点创建实例对象,实例对象用于挂载实例方法和属性,例如 props slot 356 | // (为虚拟节点绑定当前的实例对象) 357 | const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent)) 358 | //处理「组件」的初始化逻辑 359 | setupComponent(instance) 360 | //处理「元素」的渲染逻辑 361 | setupRenderEffect(instance, initialVNode, container, anchor) 362 | } 363 | 364 | /** 365 | * 在这里会调用一些 dom 的 api,将虚拟 dom 转换成真实 dom 366 | * update:支持用户传入自定义渲染器 367 | * @param vnode 368 | * @param container 369 | * @param parentComponent 370 | */ 371 | function mountElement(vnode, container, parentComponent, anchor) { 372 | const {children, props, shapeFlag, type} = vnode 373 | //创建元素,使用自定义渲染器 374 | const el = (vnode.el = hostCreateElement(type)) 375 | //创建元素内容 376 | if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { 377 | el.textContent = children 378 | } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { //children 为数组 379 | mountChildren(vnode.children, el, parentComponent, anchor) 380 | } 381 | //处理 props 382 | for (const key in props) { 383 | const val = props[key] 384 | // 自定义 props 接口 385 | hostPatchProp(el, key, null, val) 386 | } 387 | //添加到父容器 388 | hostInsert(el, container, anchor) 389 | } 390 | 391 | function mountChildren(children, container, parentComponent, anchor) { 392 | children.forEach(v => { 393 | patch(null, v, container, parentComponent, anchor) 394 | }) 395 | } 396 | 397 | /** 398 | * 该方法获取组件的整个元素树,交给 patch 去逐个处理 399 | * effect 在这里就用上了,为 render 中的响应式对象收集依赖 400 | * @param instance 401 | * @param initialVNode 402 | * @param container 403 | * @param anchor 404 | */ 405 | function setupRenderEffect(instance, initialVNode, container, anchor) { 406 | // 为当前实例赋值这个 effect 的 runner,用于更新组件的时候调用 407 | instance.update = effect(() => { 408 | if (!instance.isMounted) { // 初始化逻辑 409 | const {proxy} = instance 410 | //直接调用 instance 的 render() 获取到虚拟结点 411 | //指定 this 为代理对象,第二个参数是 _ctx 412 | const subTree = (instance.subTree = instance.render.call(proxy, proxy)) 413 | //再次调用 patch,去处理元素的渲染 414 | patch(null, subTree, container, instance, anchor) 415 | //$el挂载,这次才是获取到初始化完成的 el 416 | initialVNode.el = subTree.el 417 | instance.isMounted = true 418 | } else { //更新逻辑 419 | // next:新的虚拟节点 420 | // vnode:老的虚拟节点 421 | const {proxy, next, vnode} = instance 422 | // 更新 el 423 | if (next) { 424 | next.el = vnode.el 425 | updateComponentPreRender(instance, next) 426 | } 427 | // 获取当前组件的 subTree 以及上一次的 subTree 用于 diff 对比的 428 | const subTree = instance.render.call(proxy, proxy) 429 | const prevSubTree = instance.subTree 430 | // 完事记录一下当前的 subTree 431 | instance.subTree = subTree 432 | patch(prevSubTree, subTree, container, instance, anchor) 433 | } 434 | }, { 435 | scheduler() { 436 | queueJobs(instance.update) 437 | } 438 | }) 439 | } 440 | 441 | return { 442 | createApp: createAppAPI(render) 443 | } 444 | } 445 | 446 | /** 447 | * 组件更新,更新组件 props,封装 448 | * @param instance 组件实例 449 | * @param nextVNode 新虚拟节点 450 | */ 451 | function updateComponentPreRender(instance, nextVNode) { 452 | instance.vnode = nextVNode 453 | instance.next = null 454 | 455 | instance.props = nextVNode.props 456 | } 457 | 458 | 459 | // 最长递增子序列 460 | function getSequence(arr) { 461 | const p = arr.slice() 462 | const result = [0] 463 | let i, j, u, v, c 464 | const len = arr.length 465 | for (i = 0; i < len; i++) { 466 | const arrI = arr[i] 467 | if (arrI !== 0) { 468 | j = result[result.length - 1] 469 | if (arr[j] < arrI) { 470 | p[i] = j 471 | result.push(i) 472 | continue 473 | } 474 | u = 0 475 | v = result.length - 1 476 | while (u < v) { 477 | c = (u + v) >> 1 478 | if (arr[result[c]] < arrI) { 479 | u = c + 1 480 | } else { 481 | v = c 482 | } 483 | } 484 | if (arrI < arr[result[u]]) { 485 | if (u > 0) { 486 | p[i] = result[u - 1] 487 | } 488 | result[u] = i 489 | } 490 | } 491 | } 492 | u = result.length 493 | v = result[u - 1] 494 | while (u-- > 0) { 495 | result[u] = v 496 | v = p[v] 497 | } 498 | return result 499 | } 500 | -------------------------------------------------------------------------------- /packages/runtime-core/src/scheduler.ts: -------------------------------------------------------------------------------- 1 | const queue: any[] = [] 2 | let isFlushPending = false 3 | const p = Promise.resolve() 4 | 5 | /** 6 | * nextTick API 7 | * @param fn 8 | */ 9 | export function nextTick(fn) { 10 | return fn ? p.then(fn) : p 11 | } 12 | 13 | /** 14 | * 异步队列 15 | * @param job 任务 16 | */ 17 | export function queueJobs(job) { 18 | if (!queue.includes(job)) { 19 | queue.push(job) 20 | } 21 | queueFlush() 22 | } 23 | 24 | /** 25 | * 通过微任务的方式执行收集到的 Job 26 | */ 27 | function queueFlush() { 28 | // isFlushPending 标记当前微任务是否已经执行完毕 29 | if (isFlushPending) return 30 | // 锁住状态,以免下一个任务过来的时候又创建一个 Promise 31 | isFlushPending = true 32 | // 通过微任务执行所有 job 33 | nextTick(flushJobs) 34 | } 35 | 36 | function flushJobs() { 37 | let job 38 | while (job = queue.shift()) { 39 | job && job() 40 | } 41 | // 解锁 42 | isFlushPending = false 43 | } 44 | -------------------------------------------------------------------------------- /packages/runtime-core/src/vnode.ts: -------------------------------------------------------------------------------- 1 | import {ShapeFlags} from "@micro-vue-next/shared"; 2 | 3 | export const Fragment = Symbol("Fragment") 4 | export const Text = Symbol("Text") 5 | 6 | export { 7 | createVNode as createElementVNode 8 | } 9 | 10 | export function createVNode(type, props?, children?) { 11 | const vnode = { 12 | type, 13 | props, 14 | children, 15 | component: null, // 虚拟节点对应的实例 16 | key: props && props.key, 17 | shapeFlag: getShapeFlag(type), 18 | el: null 19 | } 20 | // 为 children 添加 shapeFlag 21 | // 通过位运算处理 22 | if (typeof children === 'string') { 23 | vnode.shapeFlag = vnode.shapeFlag | ShapeFlags.TEXT_CHILDREN 24 | } else if (Array.isArray(children)) { 25 | vnode.shapeFlag = vnode.shapeFlag | ShapeFlags.ARRAY_CHILDREN 26 | } 27 | //判断 children 是否插槽 28 | if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { 29 | if (typeof vnode.children === "object") { 30 | vnode.shapeFlag |= ShapeFlags.SLOTS_CHILDREN 31 | } 32 | } 33 | return vnode 34 | } 35 | 36 | function getShapeFlag(type) { 37 | // 判断是元素或者是组件 38 | return typeof type === 'string' ? ShapeFlags.ELEMENT : ShapeFlags.STATEFUL_COMPONENT 39 | } 40 | 41 | export function createTextVNode(text: string) { 42 | // 定义 Text 类型,渲染文本类型节点 43 | return createVNode(Text, {}, text) 44 | } 45 | -------------------------------------------------------------------------------- /packages/runtime-dom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@micro-vue-next/runtime-dom", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@micro-vue-next/runtime-core": "workspace:^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/runtime-dom/src/index.ts: -------------------------------------------------------------------------------- 1 | import {createRenderer} from "@micro-vue-next/runtime-core"; 2 | 3 | /** 4 | * 自定义渲染器,处理元素 5 | * @param type 元素类型 6 | */ 7 | function createElement(type) { 8 | return document.createElement(type) 9 | } 10 | 11 | /** 12 | * 自定义渲染器,处理 prop 13 | * @param el 元素 14 | * @param key 属性键 15 | * @param prevVal 旧属性键 16 | * @param nextVal 新属性值 17 | */ 18 | function patchProp(el, key, prevVal, nextVal) { 19 | //注册事件的逻辑 20 | const isOn = (key: string) => { 21 | return /^on[A-Z]/.test(key) 22 | } 23 | // 判断 props 是事件还是属性 24 | if (isOn(key)) { 25 | const event = key.slice(2).toLowerCase() 26 | el.addEventListener(event, nextVal) 27 | } else { 28 | if (nextVal === undefined || nextVal === null) { 29 | el.removeAttribute(key) 30 | } else { 31 | el.setAttribute(key, nextVal) 32 | } 33 | } 34 | } 35 | 36 | /** 37 | * 自定义渲染器,插入元素 38 | * @param child 元素 39 | * @param parent 需要插入的父级元素 40 | * @param anchor 锚点,指定插入的位置 41 | */ 42 | function insert(child, parent, anchor = null) { 43 | // parent.append(el) 44 | parent.insertBefore(child, anchor) 45 | } 46 | 47 | /** 48 | * 自定义渲染器,移除元素 49 | * @param child 需要移除的元素 50 | */ 51 | function remove(child) { 52 | const parent = child.parentNode 53 | if (parent) { 54 | parent.removeChild(child) 55 | } 56 | } 57 | 58 | /** 59 | * 自定义渲染器,设置元素 text 60 | * @param container 容器 61 | * @param text 设置的内容 62 | */ 63 | function setElementText(container, text) { 64 | container.textContent = text 65 | } 66 | 67 | const renderer = createRenderer({ 68 | createElement, 69 | patchProp, 70 | insert, 71 | remove, 72 | setElementText 73 | }) as any 74 | 75 | export function createApp(...args) { 76 | return renderer.createApp(...args) 77 | } 78 | 79 | // runtime-core 属于 runtime-dom 的子集,所以就直接从这里导出 80 | export * from '@micro-vue-next/runtime-core' 81 | 82 | -------------------------------------------------------------------------------- /packages/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@micro-vue-next/shared", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /packages/shared/src/ShapeFlags.ts: -------------------------------------------------------------------------------- 1 | // 用于表示结点的类型 2 | export const enum ShapeFlags { 3 | ELEMENT = 1, 4 | STATEFUL_COMPONENT = 1 << 1, //1左移一位 5 | TEXT_CHILDREN = 1 << 2, //1左移两位 6 | ARRAY_CHILDREN = 1 << 3, //1左移三位 7 | SLOTS_CHILDREN = 1 << 4 8 | } 9 | -------------------------------------------------------------------------------- /packages/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export const extend = Object.assign 2 | export const isObject = (val: any) => val !== null && typeof val === 'object' 3 | export const hasChanged = (newVal, oldVal) => !Object.is(newVal, oldVal) 4 | export const hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key) 5 | export const EMPTY_OBJ = {} 6 | export const isString = (value) => typeof value === 'string' 7 | export * from "./toDisplayString" 8 | export {ShapeFlags} from './ShapeFlags' 9 | 10 | //先将 add-foo 事件格式转换为 addFoo格式 11 | export const camelize = (str: string) => { 12 | return str.replace(/-(\w)/g, (_, c: string) => { 13 | return c ? c.toUpperCase() : "" 14 | }) 15 | } 16 | //将自定义事件的首字母转换成大写 17 | const capitalize = (str: string) => { 18 | return str.charAt(0).toUpperCase() + str.slice(1) 19 | } 20 | //统一添加 on 作为事件开头 21 | export const toHandlerKey = (str: string) => { 22 | return str ? 'on' + capitalize(str) : '' 23 | } 24 | -------------------------------------------------------------------------------- /packages/shared/src/toDisplayString.ts: -------------------------------------------------------------------------------- 1 | export function toDisplayString(value) { 2 | return String(value) 3 | } 4 | -------------------------------------------------------------------------------- /packages/vue/example/apiInject/App.js: -------------------------------------------------------------------------------- 1 | // 组件 provide 和 inject 功能 2 | import { h, provide, inject } from "../../lib/vue-next.esm.js" 3 | 4 | const Provider = { 5 | name: "Provider", 6 | setup() { 7 | provide("foo", "fooVal") 8 | provide("bar", "barVal") 9 | }, 10 | render() { 11 | return h("div", {}, [h("p", {}, "Provider"), h(ProviderTwo)]) 12 | }, 13 | } 14 | 15 | const ProviderTwo = { 16 | name: "ProviderTwo", 17 | setup() { 18 | provide("foo", "fooTwo") 19 | const foo = inject("foo") 20 | 21 | return { 22 | foo 23 | } 24 | }, 25 | render() { 26 | return h("div", {}, [h("p", {}, `ProvideTwo foo: ${this.foo}`), h(Consumer)]) 27 | // return h("div", {}, [ 28 | // h("p", {}, `ProviderTwo foo:${this.foo}`), 29 | // h(Consumer), 30 | // ]) 31 | }, 32 | } 33 | 34 | const Consumer = { 35 | name: "Consumer", 36 | setup() { 37 | const foo = inject("foo") 38 | const bar = inject("bar") 39 | // const baz = inject("baz", "bazDefault") 40 | const baz = inject("baz", () => "bazDefault") 41 | 42 | return { 43 | foo, 44 | bar, 45 | baz, 46 | } 47 | }, 48 | 49 | render() { 50 | return h("div", {}, `Consumer: - ${this.foo} - ${this.bar} - ${this.baz}`) 51 | }, 52 | } 53 | 54 | export default { 55 | name: "App", 56 | setup() {}, 57 | render() { 58 | return h("div", {}, [h("p", {}, "apiInject"), h(Provider)]) 59 | }, 60 | } 61 | -------------------------------------------------------------------------------- /packages/vue/example/apiInject/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 |
10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/vue/example/compiler-base/App.js: -------------------------------------------------------------------------------- 1 | import {ref} from "../../dist/vue-next.esm.js" 2 | 3 | // export const App = { 4 | // name: "App", 5 | // template: `
hi,{{message}} {{count}}
`, 6 | // setup() { 7 | // const count = (window.count = ref(1)) 8 | // const message = ref("mini-vue") 9 | // const changeCount = () => { 10 | // count.value++ 11 | // } 12 | // return { 13 | // count, 14 | // message, 15 | // } 16 | // }, 17 | // } 18 | 19 | export const App = { 20 | name: "App", 21 | template: `
hi,{{count}}
`, 22 | setup() { 23 | const count = (window.count = ref(1)) 24 | return { 25 | count 26 | } 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /packages/vue/example/compiler-base/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /packages/vue/example/compiler-base/main.js: -------------------------------------------------------------------------------- 1 | import {createApp} from "../../dist/vue-next.esm.js" 2 | import {App} from "./App.js" 3 | 4 | const rootContainer = document.querySelector("#app") 5 | createApp(App).mount(rootContainer) 6 | -------------------------------------------------------------------------------- /packages/vue/example/componentEmit/App.js: -------------------------------------------------------------------------------- 1 | import {h} from "/./lib/vue-next.esm.js" 2 | import {Foo} from "./Foo.js"; 3 | 4 | window.self = null 5 | export const App = { 6 | name: "APP", 7 | render() { 8 | window.self = this 9 | return h("div", 10 | {id: 'root', 'class': ["red"]}, 11 | [ 12 | h("div", {}, "App"), 13 | h(Foo, { 14 | onAdd(a, b) { 15 | console.log("on Add", a, b) 16 | }, 17 | onAddFoo(a,b){ 18 | console.log("on Add Foo",a,b) 19 | } 20 | }), 21 | ]) 22 | }, 23 | setup() { 24 | return {} 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/vue/example/componentEmit/Foo.js: -------------------------------------------------------------------------------- 1 | import {h} from "../../lib/vue-next.esm.js"; 2 | 3 | export const Foo = { 4 | setup(props, {emit}) { 5 | const emitAdd = () => { 6 | console.log("emit") 7 | emit("add", 1, 2) 8 | emit("add-foo", 1, 2) 9 | } 10 | return {emitAdd} 11 | }, 12 | render() { 13 | const btn = h("button", { 14 | onClick: this.emitAdd 15 | }, "emitAdd") 16 | const foo = h("p", {}, "foo") 17 | return h("div", {}, [foo, btn]) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/vue/example/componentEmit/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /packages/vue/example/componentEmit/main.js: -------------------------------------------------------------------------------- 1 | import {createApp} from "../../lib/vue-next.esm.js"; 2 | import {App} from "./App.js"; 3 | 4 | const rootContainer = document.querySelector("#app") 5 | createApp(App).mount(rootContainer) -------------------------------------------------------------------------------- /packages/vue/example/componentSlot/App.js: -------------------------------------------------------------------------------- 1 | import { h, createTextVNode } from "../../lib/vue-next.esm.js" 2 | import { Foo } from "./Foo.js" 3 | 4 | export const App = { 5 | name: "App", 6 | render() { 7 | const app = h("div", {}, "App") 8 | // object key 9 | const foo = h( 10 | Foo, 11 | {}, 12 | // children被Foo的slots拿到并渲染 13 | // h('p', {}, '123') 14 | // 如果是数组的 15 | // [h('p', {}, '123'), h('p', {}, '456')] 16 | // { 17 | // header: h('p', {}, 'header'), 18 | // footer: h('p', {}, 'footer'), 19 | // } 20 | { 21 | header: ({ age }) => [h("p", {}, "header" + age), 22 | createTextVNode('你好呀')], 23 | footer: () => h("p", {}, "footer"), 24 | } 25 | ) 26 | // 数组 vnode 27 | // const foo = h(Foo, {}, h("p", {}, "123")); 28 | return h("div", {}, [app, foo]) 29 | }, 30 | 31 | setup() { 32 | return {} 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /packages/vue/example/componentSlot/Foo.js: -------------------------------------------------------------------------------- 1 | import { h, renderSlots } from "../../lib/vue-next.esm.js" 2 | 3 | export const Foo = { 4 | setup() { 5 | return {} 6 | }, 7 | render() { 8 | const foo = h("p", {}, "foo") 9 | 10 | // Foo .vnode. children 11 | // console.log(this.$slots) 12 | // children -> vnode 13 | // 14 | // renderSlots 15 | // 具名插槽 16 | // 1. 获取到要渲染的元素 1 17 | // 2. 要获取到渲染的位置 18 | // 作用域插槽 19 | const age = 18 20 | // 这时slots是通过children获取到的 21 | // 当是数组的时候,就要将数组转为vnode,因此再一次h 22 | // return h("div", {}, [foo, h('div', {}, this.$slots)] 23 | return h( 24 | "div", 25 | {}, 26 | [ 27 | renderSlots(this.$slots, "header", {age}), 28 | foo, 29 | renderSlots(this.$slots, "footer"), 30 | ] 31 | // [ 32 | // renderSlots(this.$slots, "header", { 33 | // age, 34 | // }), 35 | // foo, 36 | // renderSlots(this.$slots, "footer"), 37 | // ] 38 | ) 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /packages/vue/example/componentSlot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /packages/vue/example/componentSlot/main.js: -------------------------------------------------------------------------------- 1 | import {createApp} from "../../lib/vue-next.esm.js"; 2 | import {App} from "./App.js"; 3 | 4 | const rootContainer = document.querySelector("#app") 5 | createApp(App).mount(rootContainer) -------------------------------------------------------------------------------- /packages/vue/example/componentUpdate/App.js: -------------------------------------------------------------------------------- 1 | import { h, ref } from "../../lib/vue-next.esm.js" 2 | import Child from "./Child.js" 3 | 4 | export const App = { 5 | name: "App", 6 | setup() { 7 | const msg = ref("123") 8 | const count = ref(1) 9 | 10 | window.msg = msg 11 | 12 | const changeChildProps = () => { 13 | msg.value = "456" 14 | } 15 | 16 | const changeCount = () => { 17 | count.value++ 18 | } 19 | 20 | return { msg, changeChildProps, changeCount, count } 21 | }, 22 | 23 | render() { 24 | return h("div", {}, [ 25 | h("div", {}, "你好"), 26 | h( 27 | "button", 28 | { 29 | onClick: this.changeChildProps, 30 | }, 31 | "change child props" 32 | ), 33 | h(Child, { 34 | msg: this.msg, 35 | }), 36 | h( 37 | "button", 38 | { 39 | onClick: this.changeCount, 40 | }, 41 | "change self count" 42 | ), 43 | h("p", {}, "count: " + this.count), 44 | ]) 45 | }, 46 | } 47 | -------------------------------------------------------------------------------- /packages/vue/example/componentUpdate/Child.js: -------------------------------------------------------------------------------- 1 | import { h } from "../../lib/vue-next.esm.js" 2 | export default { 3 | name: "Child", 4 | setup(props, { emit }) {}, 5 | render(proxy) { 6 | return h("div", {}, [ 7 | h("div", {}, "child - props - msg: " + this.$props.msg), 8 | ]) 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /packages/vue/example/componentUpdate/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 |
10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/vue/example/currentInstance/App.js: -------------------------------------------------------------------------------- 1 | import {h, getCurrentInstance} from "../../lib/vue-next.esm.js" 2 | import {Foo} from "./Foo.js" 3 | 4 | export const App = { 5 | name: "App", 6 | render() { 7 | return h("div", {}, [h("p", {}, "current instance demo"), h(Foo)]) 8 | }, 9 | 10 | setup() { 11 | const instance = getCurrentInstance() 12 | console.log("App:", instance) 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /packages/vue/example/currentInstance/Foo.js: -------------------------------------------------------------------------------- 1 | import { h,getCurrentInstance } from "../../lib/vue-next.esm.js" 2 | 3 | export const Foo = { 4 | setup() { 5 | const instance = getCurrentInstance() 6 | console.log("Foo:", instance) 7 | }, 8 | render() { 9 | return h("div",{},"foo") 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /packages/vue/example/currentInstance/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /packages/vue/example/currentInstance/main.js: -------------------------------------------------------------------------------- 1 | import {createApp} from "../../lib/vue-next.esm.js"; 2 | import {App} from "./App.js"; 3 | 4 | const rootContainer = document.querySelector("#app") 5 | createApp(App).mount(rootContainer) -------------------------------------------------------------------------------- /packages/vue/example/customRenderer/App.js: -------------------------------------------------------------------------------- 1 | import {h} from "../../lib/vue-next.esm.js" 2 | 3 | export const App = { 4 | setup() { 5 | return { 6 | x: 100, 7 | y: 100 8 | } 9 | }, 10 | render() { 11 | return h("rect", {x: this.x, y: this.y}) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/vue/example/customRenderer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/vue/example/customRenderer/main.js: -------------------------------------------------------------------------------- 1 | import {createRenderer} from "../../lib/vue-next.esm.js"; 2 | import {App} from "./App.js"; 3 | 4 | const game = new PIXI.Application({ 5 | width: 500, 6 | height: 500 7 | }) 8 | 9 | document.body.append(game.view) 10 | 11 | const renderer = createRenderer({ 12 | //自定义渲染器 13 | createElement(type) { 14 | if (type === "rect") { 15 | const rect = new PIXI.Graphics() 16 | rect.beginFill(0xff0000) 17 | rect.drawRect(0, 0, 100, 100) 18 | rect.endFill() 19 | return rect 20 | } 21 | }, 22 | patchProp(el, key, val) { 23 | el[key] = val 24 | }, 25 | insert(el, parent) { 26 | parent.addChild(el) 27 | } 28 | }) 29 | 30 | renderer.createApp(App).mount(game.stage) 31 | 32 | // const rootContainer = document.querySelector("#app") 33 | // createApp(App).mount(rootContainer) 34 | -------------------------------------------------------------------------------- /packages/vue/example/helloworld/App.js: -------------------------------------------------------------------------------- 1 | import {h} from "../../dist/vue-next.esm.js" 2 | import {Foo} from "./Foo.js"; 3 | 4 | window.self = null 5 | export const App = { 6 | name: "APP", 7 | render() { 8 | window.self = this 9 | return h("div", 10 | {id: 'root', 'class': ["red", "hard"]}, 11 | [ 12 | h("div", {}, "hi," + this.msg), 13 | h(Foo, {count: 1}), 14 | ]) 15 | }, 16 | setup() { 17 | return { 18 | msg: "mini-vue-flash" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/vue/example/helloworld/Foo.js: -------------------------------------------------------------------------------- 1 | import {h} from "../../dist/vue-next.esm.js"; 2 | 3 | export const Foo = { 4 | setup(props) { 5 | //count 6 | props.count ++ 7 | console.log(props); 8 | }, 9 | render() { 10 | return h("div", {}, "foo:" + this.count) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/vue/example/helloworld/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /packages/vue/example/helloworld/main.js: -------------------------------------------------------------------------------- 1 | import {createApp} from "../../dist/vue-next.esm.js"; 2 | import {App} from "./App.js"; 3 | 4 | const rootContainer = document.querySelector("#app") 5 | createApp(App).mount(rootContainer) 6 | -------------------------------------------------------------------------------- /packages/vue/example/nexttick/App.js: -------------------------------------------------------------------------------- 1 | import { 2 | h, 3 | ref, 4 | getCurrentInstance, 5 | nextTick 6 | } from "../../lib/vue-next.esm.js" 7 | 8 | export default { 9 | name: "App", 10 | setup() { 11 | const count = ref(1) 12 | const instance = getCurrentInstance() 13 | 14 | function onClick() { 15 | for (let i = 0; i < 100; i++) { 16 | count.value = i 17 | } 18 | nextTick(() => { 19 | console.log(instance) 20 | }) 21 | 22 | // await nextTick() 23 | // console.log(instance) 24 | } 25 | 26 | return { 27 | onClick, 28 | count, 29 | } 30 | }, 31 | render() { 32 | const button = h("button", { onClick: this.onClick }, "update") 33 | const p = h("p", {}, "count:" + this.count) 34 | 35 | return h("div", {}, [button, p]) 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /packages/vue/example/nexttick/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/vue/example/nexttick/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from "../../lib/vue-next.esm.js" 2 | import App from "./App.js" 3 | 4 | const rootContainer = document.querySelector("#root") 5 | createApp(App).mount(rootContainer) 6 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/App.js: -------------------------------------------------------------------------------- 1 | import { h } from "../../lib/vue-next.esm.js" 2 | 3 | import ArrayToText from "./ArrayToText.js" 4 | import TextToText from "./TextToText.js" 5 | import TextToArray from "./TextToArray.js" 6 | import ArrayToArray from "./ArrayToArray.js" 7 | 8 | export default { 9 | name: "App", 10 | setup() {}, 11 | 12 | render() { 13 | return h("div", { tId: 1 }, [ 14 | h("p", {}, "主页"), 15 | // 老的是 array 新的是 text 16 | // h(ArrayToText), 17 | // 老的是 text 新的是 text 18 | // h(TextToText), 19 | // 老的是 text 新的是 array 20 | //h(TextToArray), 21 | // 老的是 array 新的是 array 22 | h(ArrayToArray) 23 | ]) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/ArrayToArray.js: -------------------------------------------------------------------------------- 1 | // TODO 2 | // 老的是 array 3 | // 新的是 array 4 | 5 | import {ref, h} from "../../lib/vue-next.esm.js" 6 | 7 | // 1. 左侧的对比 8 | // (a b) c 9 | // (a b) d e 10 | // const prevChildren = [ 11 | // h("p", { key: "A" }, "A"), 12 | // h("p", { key: "B" }, "B"), 13 | // h("p", { key: "C" }, "C"), 14 | // ]; 15 | // const nextChildren = [ 16 | // h("p", { key: "A" }, "A"), 17 | // h("p", { key: "B" }, "B"), 18 | // h("p", { key: "D" }, "D"), 19 | // h("p", { key: "E" }, "E"), 20 | // ]; 21 | 22 | // 2. 右侧的对比 23 | // a (b c) 24 | // d e (b c) 25 | // const prevChildren = [ 26 | // h("p", { key: "A" }, "A"), 27 | // h("p", { key: "B" }, "B"), 28 | // h("p", { key: "C" }, "C"), 29 | // ]; 30 | // const nextChildren = [ 31 | // h("p", { key: "D" }, "D"), 32 | // h("p", { key: "E" }, "E"), 33 | // h("p", { key: "B" }, "B"), 34 | // h("p", { key: "C" }, "C"), 35 | // ]; 36 | 37 | // 3. 新的比老的长 38 | // 创建新的 39 | // 左侧 40 | // (a b) 41 | // (a b) c 42 | // i = 2, e1 = 1, e2 = 2 43 | // const prevChildren = [h("p", { key: "A" }, "A"), h("p", { key: "B" }, "B")]; 44 | // const nextChildren = [ 45 | // h("p", { key: "A" }, "A"), 46 | // h("p", { key: "B" }, "B"), 47 | // h("p", { key: "C" }, "C"), 48 | // h("p", { key: "D" }, "D"), 49 | // h("p", { key: "E" }, "E"), 50 | // h("p", { key: "F" }, "F"), 51 | // ]; 52 | 53 | // 右侧 54 | // (a b) 55 | // c (a b) 56 | // i = 0, e1 = -1, e2 = 0 57 | // const prevChildren = [h("p", { key: "A" }, "A"), h("p", { key: "B" }, "B")]; 58 | // const nextChildren = [ 59 | // h("p", { key: "F" }, "F"), 60 | // h("p", { key: "E" }, "E"), 61 | // h("p", { key: "D" }, "D"), 62 | // h("p", { key: "C" }, "C"), 63 | // h("p", { key: "A" }, "A"), 64 | // h("p", { key: "B" }, "B"), 65 | // ]; 66 | 67 | // 4. 老的比新的长 68 | // 删除老的 69 | // 左侧 70 | // (a b) c 71 | // (a b) 72 | // i = 2, e1 = 2, e2 = 1 73 | // const prevChildren = [ 74 | // h("p", { key: "A" }, "A"), 75 | // h("p", { key: "B" }, "B"), 76 | // h("p", { key: "C" }, "C"), 77 | // ]; 78 | // const nextChildren = [h("p", { key: "A" }, "A"), h("p", { key: "B" }, "B")]; 79 | 80 | // 右侧 81 | // a (b c) 82 | // (b c) 83 | // i = 0, e1 = 0, e2 = -1 84 | // const prevChildren = [ 85 | // h("p", { key: "A" }, "A"), 86 | // h("p", { key: "B" }, "B"), 87 | // h("p", { key: "C" }, "C"), 88 | // ] 89 | // const nextChildren = [h("p", { key: "B" }, "B"), h("p", { key: "C" }, "C")] 90 | 91 | // 5. 对比中间的部分 92 | // 1. 创建新的 (在老的里面不存在,新的里面存在) 93 | // 2. 删除老的 (在老的里面存在,新的里面不存在) 94 | // 3. 移动 (节点存在于新的和老的里面,但是位置变了) 95 | // - 使用最长子序列来优化 96 | 97 | // 删除老的 (在老的里面存在,新的里面不存在) 98 | // 5.1 99 | // a,b,(c,d),f,g 100 | // a,b,(e,c),f,g 101 | // D 节点在新的里面是没有的 - 需要删除掉 102 | // C 节点 props 也发生了变化 103 | // const prevChildren = [ 104 | // h("p", { key: "A" }, "A"), 105 | // h("p", { key: "B" }, "B"), 106 | // h("p", { key: "C", id: "c-prev" }, "C"), 107 | // h("p", { key: "D" }, "D"), 108 | // h("p", { key: "F" }, "F"), 109 | // h("p", { key: "G" }, "G"), 110 | // ]; 111 | // const nextChildren = [ 112 | // h("p", { key: "A" }, "A"), 113 | // h("p", { key: "B" }, "B"), 114 | // h("p", { key: "E" }, "E"), 115 | // h("p", { key: "C", id:"c-next" }, "C"), 116 | // h("p", { key: "F" }, "F"), 117 | // h("p", { key: "G" }, "G"), 118 | // ]; 119 | 120 | 121 | // 5.1.1 122 | // a,b,(c,e,d),f,g 123 | // a,b,(e,c),f,g 124 | // 中间部分,老的比新的多, 那么多出来的直接就可以被干掉(优化删除逻辑) 125 | // const prevChildren = [ 126 | // h("p", { key: "A" }, "A"), 127 | // h("p", { key: "B" }, "B"), 128 | // h("p", { key: "C", id: "c-prev" }, "C"), 129 | // h("p", { key: "E" }, "E"), 130 | // h("p", { key: "D" }, "D"), 131 | // h("p", { key: "F" }, "F"), 132 | // h("p", { key: "G" }, "G"), 133 | // ]; 134 | // 135 | // const nextChildren = [ 136 | // h("p", { key: "A" }, "A"), 137 | // h("p", { key: "B" }, "B"), 138 | // h("p", { key: "E" }, "E"), 139 | // h("p", { key: "C", id:"c-next" }, "C"), 140 | // h("p", { key: "F" }, "F"), 141 | // h("p", { key: "G" }, "G"), 142 | // ]; 143 | 144 | 145 | // 2 移动 (节点存在于新的和老的里面,但是位置变了) 146 | // 2.1 147 | // a,b,(c,d,e),f,g 148 | // a,b,(e,c,d),f,g 149 | // 最长子序列: [1,2] 150 | // const prevChildren = [ 151 | // h("p", { key: "A" }, "A"), 152 | // h("p", { key: "B" }, "B"), 153 | // h("p", { key: "C" }, "C"), 154 | // h("p", { key: "D" }, "D"), 155 | // h("p", { key: "E" }, "E"), 156 | // h("p", { key: "F" }, "F"), 157 | // h("p", { key: "G" }, "G"), 158 | // ]; 159 | // 160 | // const nextChildren = [ 161 | // h("p", { key: "A" }, "A"), 162 | // h("p", { key: "B" }, "B"), 163 | // h("p", { key: "E" }, "E"), 164 | // h("p", { key: "C" }, "C"), 165 | // h("p", { key: "D" }, "D"), 166 | // h("p", { key: "F" }, "F"), 167 | // h("p", { key: "G" }, "G"), 168 | // ]; 169 | 170 | // 3. 创建新的节点 171 | // a,b,(c,e),f,g 172 | // a,b,(e,c,d),f,g 173 | // d 节点在老的节点中不存在,新的里面存在,所以需要创建 174 | // const prevChildren = [ 175 | // h("p", { key: "A" }, "A"), 176 | // h("p", { key: "B" }, "B"), 177 | // h("p", { key: "C" }, "C"), 178 | // h("p", { key: "E" }, "E"), 179 | // h("p", { key: "F" }, "F"), 180 | // h("p", { key: "G" }, "G"), 181 | // ]; 182 | // 183 | // const nextChildren = [ 184 | // h("p", { key: "A" }, "A"), 185 | // h("p", { key: "B" }, "B"), 186 | // h("p", { key: "E" }, "E"), 187 | // h("p", { key: "C" }, "C"), 188 | // h("p", { key: "D" }, "D"), 189 | // h("p", { key: "F" }, "F"), 190 | // h("p", { key: "G" }, "G"), 191 | // ]; 192 | 193 | // 综合例子 194 | // a,b,(c,d,e,z),f,g 195 | // a,b,(d,c,y,e),f,g 196 | // const prevChildren = [ 197 | // h("p", { key: "A" }, "A"), 198 | // h("p", { key: "B" }, "B"), 199 | // h("p", { key: "C" }, "C"), 200 | // h("p", { key: "D" }, "D"), 201 | // h("p", { key: "E" }, "E"), 202 | // h("p", { key: "Z" }, "Z"), 203 | // h("p", { key: "F" }, "F"), 204 | // h("p", { key: "G" }, "G"), 205 | // ]; 206 | // 207 | // const nextChildren = [ 208 | // h("p", { key: "A" }, "A"), 209 | // h("p", { key: "B" }, "B"), 210 | // h("p", { key: "D" }, "D"), 211 | // h("p", { key: "C" }, "C"), 212 | // h("p", { key: "Y" }, "Y"), 213 | // h("p", { key: "E" }, "E"), 214 | // h("p", { key: "F" }, "F"), 215 | // h("p", { key: "G" }, "G"), 216 | // ]; 217 | 218 | // fix c 节点应该被移动,而不是被删除后重新创建 219 | const prevChildren = [ 220 | h("p", {key: "A"}, "A"), 221 | h("p", {}, "C"), 222 | h("p", {key: "B"}, "B"), 223 | h("p", {key: "D"}, "D"), 224 | ]; 225 | 226 | const nextChildren = [ 227 | h("p", {key: "A"}, "A"), 228 | h("p", {key: "B"}, "B"), 229 | h("p", {}, "C"), 230 | h("p", {key: "D"}, "D"), 231 | ]; 232 | 233 | export default { 234 | name: "ArrayToArray", 235 | setup() { 236 | const isChange = ref(false) 237 | window.isChange = isChange 238 | 239 | return { 240 | isChange, 241 | } 242 | }, 243 | render() { 244 | const self = this 245 | 246 | return self.isChange === true 247 | ? h("div", {}, nextChildren) 248 | : h("div", {}, prevChildren) 249 | }, 250 | } 251 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/ArrayToText.js: -------------------------------------------------------------------------------- 1 | // 老的是 array 2 | // 新的是 text 3 | 4 | import { ref, h } from "../../lib/vue-next.esm.js" 5 | const nextChildren = "newChildren" 6 | const prevChildren = [h("div", {}, "A"), h("div", {}, "B")] 7 | 8 | export default { 9 | name: "ArrayToText", 10 | setup() { 11 | const isChange = ref(false) 12 | window.isChange = isChange 13 | 14 | return { 15 | isChange, 16 | } 17 | }, 18 | render() { 19 | const self = this 20 | 21 | return self.isChange === true 22 | ? h("div", {}, nextChildren) 23 | : h("div", {}, prevChildren) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/TextToArray.js: -------------------------------------------------------------------------------- 1 | // 新的是 array 2 | // 老的是 text 3 | import { ref, h } from "../../lib/vue-next.esm.js" 4 | 5 | const prevChildren = "oldChild" 6 | const nextChildren = [h("div", {}, "A"), h("div", {}, "B")] 7 | 8 | export default { 9 | name: "TextToArray", 10 | setup() { 11 | const isChange = ref(false) 12 | window.isChange = isChange 13 | 14 | return { 15 | isChange, 16 | } 17 | }, 18 | render() { 19 | const self = this 20 | 21 | return self.isChange === true 22 | ? h("div", {}, nextChildren) 23 | : h("div", {}, prevChildren) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/TextToText.js: -------------------------------------------------------------------------------- 1 | // 新的是 text 2 | // 老的是 text 3 | import { ref, h } from "../../lib/vue-next.esm.js" 4 | 5 | const prevChildren = "oldChild" 6 | const nextChildren = "newChild" 7 | 8 | export default { 9 | name: "TextToText", 10 | setup() { 11 | const isChange = ref(false) 12 | window.isChange = isChange 13 | 14 | return { 15 | isChange, 16 | } 17 | }, 18 | render() { 19 | const self = this 20 | 21 | return self.isChange === true 22 | ? h("div", {}, nextChildren) 23 | : h("div", {}, prevChildren) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/vue/example/patchChildren/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from "../../lib/vue-next.esm.js" 2 | import App from "./App.js" 3 | 4 | const rootContainer = document.querySelector("#root") 5 | createApp(App).mount(rootContainer) 6 | -------------------------------------------------------------------------------- /packages/vue/example/update/App.js: -------------------------------------------------------------------------------- 1 | import { h, ref } from "../../lib/vue-next.esm.js" 2 | export const App = { 3 | name: "App", 4 | setup() { 5 | const count = ref(0) 6 | const onClick = () => { 7 | count.value++ 8 | } 9 | 10 | const props = ref({ 11 | foo: "foo", 12 | bar: "bar", 13 | }) 14 | const onChangePropsDemo1 = () => { 15 | props.value.foo = "new-foo" 16 | } 17 | 18 | const onChangePropsDemo2 = () => { 19 | props.value.foo = undefined 20 | } 21 | 22 | const onChangePropsDemo3 = () => { 23 | props.value = { 24 | foo: "foo", 25 | } 26 | } 27 | 28 | return { 29 | count, 30 | onClick, 31 | onChangePropsDemo1, 32 | onChangePropsDemo2, 33 | onChangePropsDemo3, 34 | props, 35 | } 36 | }, 37 | render() { 38 | return h( 39 | "div", 40 | { 41 | id: "root", 42 | ...this.props, 43 | }, 44 | [ 45 | h("div", {}, "count:" + this.count), // 依赖收集 46 | // h("div", {}, "count:" + this.count), 47 | h( 48 | "button", 49 | { 50 | onClick: this.onClick, 51 | }, 52 | "click" 53 | ), 54 | h( 55 | "button", 56 | { 57 | onClick: this.onChangePropsDemo1, 58 | }, 59 | "changeProps - 值改变了 - 修改" 60 | ), 61 | 62 | h( 63 | "button", 64 | { 65 | onClick: this.onChangePropsDemo2, 66 | }, 67 | "changeProps - 值变成了 undefined - 删除" 68 | ), 69 | 70 | h( 71 | "button", 72 | { 73 | onClick: this.onChangePropsDemo3, 74 | }, 75 | "changeProps - key 在新的里面没有了 - 删除" 76 | ), 77 | ] 78 | ) 79 | }, 80 | } 81 | -------------------------------------------------------------------------------- /packages/vue/example/update/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /packages/vue/example/update/main.js: -------------------------------------------------------------------------------- 1 | import { App } from './app.js' 2 | import { createApp } from '../../lib/vue-next.esm.js' 3 | 4 | const rootContainer = document.getElementById('app') 5 | createApp(App).mount(rootContainer) 6 | -------------------------------------------------------------------------------- /packages/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "micro-vue-next", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@micro-vue-next/compiler-core": "workspace:^1.0.0", 14 | "@micro-vue-next/runtime-dom": "workspace:^1.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/vue/src/index.ts: -------------------------------------------------------------------------------- 1 | //vue 出口 2 | export * from '@micro-vue-next/runtime-dom' 3 | import {baseCompile} from "@micro-vue-next/compiler-core/src" 4 | import * as runtimeDom from "@micro-vue-next/runtime-dom" 5 | import {registerRuntimeCompiler} from "@micro-vue-next/runtime-dom" 6 | 7 | /** 8 | * 将 code 包装成 function 9 | * @param template 10 | */ 11 | function compileToFunction(template) { 12 | const {code} = baseCompile(template) 13 | return new Function("Vue", code)(runtimeDom) 14 | } 15 | 16 | registerRuntimeCompiler(compileToFunction) 17 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | importers: 4 | 5 | .: 6 | specifiers: 7 | '@babel/core': ^7.17.5 8 | '@babel/preset-env': ^7.16.11 9 | '@babel/preset-typescript': ^7.16.7 10 | '@rollup/plugin-typescript': ^8.3.1 11 | rollup: ^2.70.1 12 | tslib: ^2.3.1 13 | typescript: ^4.5.5 14 | vitest: ^0.24.3 15 | devDependencies: 16 | '@babel/core': 7.19.3 17 | '@babel/preset-env': 7.19.4_@babel+core@7.19.3 18 | '@babel/preset-typescript': 7.18.6_@babel+core@7.19.3 19 | '@rollup/plugin-typescript': 8.5.0_hafrwlgfjmvsm7253l3bfjzhnq 20 | rollup: 2.79.1 21 | tslib: 2.4.0 22 | typescript: 4.8.4 23 | vitest: 0.24.3 24 | 25 | packages/compiler-core: 26 | specifiers: 27 | '@micro-vue-next/shared': workspace:^1.0.0 28 | dependencies: 29 | '@micro-vue-next/shared': link:../shared 30 | 31 | packages/reactivity: 32 | specifiers: 33 | '@micro-vue-next/shared': workspace:^1.0.0 34 | dependencies: 35 | '@micro-vue-next/shared': link:../shared 36 | 37 | packages/runtime-core: 38 | specifiers: 39 | '@micro-vue-next/reactivity': workspace:^1.0.0 40 | '@micro-vue-next/shared': workspace:^1.0.0 41 | dependencies: 42 | '@micro-vue-next/reactivity': link:../reactivity 43 | '@micro-vue-next/shared': link:../shared 44 | 45 | packages/runtime-dom: 46 | specifiers: 47 | '@micro-vue-next/runtime-core': workspace:^1.0.0 48 | dependencies: 49 | '@micro-vue-next/runtime-core': link:../runtime-core 50 | 51 | packages/vue: 52 | specifiers: 53 | '@micro-vue-next/compiler-core': workspace:^1.0.0 54 | '@micro-vue-next/runtime-dom': workspace:^1.0.0 55 | dependencies: 56 | '@micro-vue-next/compiler-core': link:../compiler-core 57 | '@micro-vue-next/runtime-dom': link:../runtime-dom 58 | 59 | packages: 60 | 61 | /@ampproject/remapping/2.2.0: 62 | resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} 63 | engines: {node: '>=6.0.0'} 64 | dependencies: 65 | '@jridgewell/gen-mapping': 0.1.1 66 | '@jridgewell/trace-mapping': 0.3.17 67 | dev: true 68 | 69 | /@babel/code-frame/7.18.6: 70 | resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} 71 | engines: {node: '>=6.9.0'} 72 | dependencies: 73 | '@babel/highlight': 7.18.6 74 | dev: true 75 | 76 | /@babel/compat-data/7.19.4: 77 | resolution: {integrity: sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==} 78 | engines: {node: '>=6.9.0'} 79 | dev: true 80 | 81 | /@babel/core/7.19.3: 82 | resolution: {integrity: sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==} 83 | engines: {node: '>=6.9.0'} 84 | dependencies: 85 | '@ampproject/remapping': 2.2.0 86 | '@babel/code-frame': 7.18.6 87 | '@babel/generator': 7.19.5 88 | '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.3 89 | '@babel/helper-module-transforms': 7.19.0 90 | '@babel/helpers': 7.19.4 91 | '@babel/parser': 7.19.4 92 | '@babel/template': 7.18.10 93 | '@babel/traverse': 7.19.4 94 | '@babel/types': 7.19.4 95 | convert-source-map: 1.9.0 96 | debug: 4.3.4 97 | gensync: 1.0.0-beta.2 98 | json5: 2.2.1 99 | semver: 6.3.0 100 | transitivePeerDependencies: 101 | - supports-color 102 | dev: true 103 | 104 | /@babel/generator/7.19.5: 105 | resolution: {integrity: sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==} 106 | engines: {node: '>=6.9.0'} 107 | dependencies: 108 | '@babel/types': 7.19.4 109 | '@jridgewell/gen-mapping': 0.3.2 110 | jsesc: 2.5.2 111 | dev: true 112 | 113 | /@babel/helper-annotate-as-pure/7.18.6: 114 | resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} 115 | engines: {node: '>=6.9.0'} 116 | dependencies: 117 | '@babel/types': 7.19.4 118 | dev: true 119 | 120 | /@babel/helper-builder-binary-assignment-operator-visitor/7.18.9: 121 | resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} 122 | engines: {node: '>=6.9.0'} 123 | dependencies: 124 | '@babel/helper-explode-assignable-expression': 7.18.6 125 | '@babel/types': 7.19.4 126 | dev: true 127 | 128 | /@babel/helper-compilation-targets/7.19.3_@babel+core@7.19.3: 129 | resolution: {integrity: sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==} 130 | engines: {node: '>=6.9.0'} 131 | peerDependencies: 132 | '@babel/core': ^7.0.0 133 | dependencies: 134 | '@babel/compat-data': 7.19.4 135 | '@babel/core': 7.19.3 136 | '@babel/helper-validator-option': 7.18.6 137 | browserslist: 4.21.4 138 | semver: 6.3.0 139 | dev: true 140 | 141 | /@babel/helper-create-class-features-plugin/7.19.0_@babel+core@7.19.3: 142 | resolution: {integrity: sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==} 143 | engines: {node: '>=6.9.0'} 144 | peerDependencies: 145 | '@babel/core': ^7.0.0 146 | dependencies: 147 | '@babel/core': 7.19.3 148 | '@babel/helper-annotate-as-pure': 7.18.6 149 | '@babel/helper-environment-visitor': 7.18.9 150 | '@babel/helper-function-name': 7.19.0 151 | '@babel/helper-member-expression-to-functions': 7.18.9 152 | '@babel/helper-optimise-call-expression': 7.18.6 153 | '@babel/helper-replace-supers': 7.19.1 154 | '@babel/helper-split-export-declaration': 7.18.6 155 | transitivePeerDependencies: 156 | - supports-color 157 | dev: true 158 | 159 | /@babel/helper-create-regexp-features-plugin/7.19.0_@babel+core@7.19.3: 160 | resolution: {integrity: sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==} 161 | engines: {node: '>=6.9.0'} 162 | peerDependencies: 163 | '@babel/core': ^7.0.0 164 | dependencies: 165 | '@babel/core': 7.19.3 166 | '@babel/helper-annotate-as-pure': 7.18.6 167 | regexpu-core: 5.2.1 168 | dev: true 169 | 170 | /@babel/helper-define-polyfill-provider/0.3.3_@babel+core@7.19.3: 171 | resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} 172 | peerDependencies: 173 | '@babel/core': ^7.4.0-0 174 | dependencies: 175 | '@babel/core': 7.19.3 176 | '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.3 177 | '@babel/helper-plugin-utils': 7.19.0 178 | debug: 4.3.4 179 | lodash.debounce: 4.0.8 180 | resolve: 1.22.1 181 | semver: 6.3.0 182 | transitivePeerDependencies: 183 | - supports-color 184 | dev: true 185 | 186 | /@babel/helper-environment-visitor/7.18.9: 187 | resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} 188 | engines: {node: '>=6.9.0'} 189 | dev: true 190 | 191 | /@babel/helper-explode-assignable-expression/7.18.6: 192 | resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} 193 | engines: {node: '>=6.9.0'} 194 | dependencies: 195 | '@babel/types': 7.19.4 196 | dev: true 197 | 198 | /@babel/helper-function-name/7.19.0: 199 | resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} 200 | engines: {node: '>=6.9.0'} 201 | dependencies: 202 | '@babel/template': 7.18.10 203 | '@babel/types': 7.19.4 204 | dev: true 205 | 206 | /@babel/helper-hoist-variables/7.18.6: 207 | resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} 208 | engines: {node: '>=6.9.0'} 209 | dependencies: 210 | '@babel/types': 7.19.4 211 | dev: true 212 | 213 | /@babel/helper-member-expression-to-functions/7.18.9: 214 | resolution: {integrity: sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==} 215 | engines: {node: '>=6.9.0'} 216 | dependencies: 217 | '@babel/types': 7.19.4 218 | dev: true 219 | 220 | /@babel/helper-module-imports/7.18.6: 221 | resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} 222 | engines: {node: '>=6.9.0'} 223 | dependencies: 224 | '@babel/types': 7.19.4 225 | dev: true 226 | 227 | /@babel/helper-module-transforms/7.19.0: 228 | resolution: {integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==} 229 | engines: {node: '>=6.9.0'} 230 | dependencies: 231 | '@babel/helper-environment-visitor': 7.18.9 232 | '@babel/helper-module-imports': 7.18.6 233 | '@babel/helper-simple-access': 7.19.4 234 | '@babel/helper-split-export-declaration': 7.18.6 235 | '@babel/helper-validator-identifier': 7.19.1 236 | '@babel/template': 7.18.10 237 | '@babel/traverse': 7.19.4 238 | '@babel/types': 7.19.4 239 | transitivePeerDependencies: 240 | - supports-color 241 | dev: true 242 | 243 | /@babel/helper-optimise-call-expression/7.18.6: 244 | resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} 245 | engines: {node: '>=6.9.0'} 246 | dependencies: 247 | '@babel/types': 7.19.4 248 | dev: true 249 | 250 | /@babel/helper-plugin-utils/7.19.0: 251 | resolution: {integrity: sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==} 252 | engines: {node: '>=6.9.0'} 253 | dev: true 254 | 255 | /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.19.3: 256 | resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} 257 | engines: {node: '>=6.9.0'} 258 | peerDependencies: 259 | '@babel/core': ^7.0.0 260 | dependencies: 261 | '@babel/core': 7.19.3 262 | '@babel/helper-annotate-as-pure': 7.18.6 263 | '@babel/helper-environment-visitor': 7.18.9 264 | '@babel/helper-wrap-function': 7.19.0 265 | '@babel/types': 7.19.4 266 | transitivePeerDependencies: 267 | - supports-color 268 | dev: true 269 | 270 | /@babel/helper-replace-supers/7.19.1: 271 | resolution: {integrity: sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==} 272 | engines: {node: '>=6.9.0'} 273 | dependencies: 274 | '@babel/helper-environment-visitor': 7.18.9 275 | '@babel/helper-member-expression-to-functions': 7.18.9 276 | '@babel/helper-optimise-call-expression': 7.18.6 277 | '@babel/traverse': 7.19.4 278 | '@babel/types': 7.19.4 279 | transitivePeerDependencies: 280 | - supports-color 281 | dev: true 282 | 283 | /@babel/helper-simple-access/7.19.4: 284 | resolution: {integrity: sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==} 285 | engines: {node: '>=6.9.0'} 286 | dependencies: 287 | '@babel/types': 7.19.4 288 | dev: true 289 | 290 | /@babel/helper-skip-transparent-expression-wrappers/7.18.9: 291 | resolution: {integrity: sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==} 292 | engines: {node: '>=6.9.0'} 293 | dependencies: 294 | '@babel/types': 7.19.4 295 | dev: true 296 | 297 | /@babel/helper-split-export-declaration/7.18.6: 298 | resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} 299 | engines: {node: '>=6.9.0'} 300 | dependencies: 301 | '@babel/types': 7.19.4 302 | dev: true 303 | 304 | /@babel/helper-string-parser/7.19.4: 305 | resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} 306 | engines: {node: '>=6.9.0'} 307 | dev: true 308 | 309 | /@babel/helper-validator-identifier/7.19.1: 310 | resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} 311 | engines: {node: '>=6.9.0'} 312 | dev: true 313 | 314 | /@babel/helper-validator-option/7.18.6: 315 | resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} 316 | engines: {node: '>=6.9.0'} 317 | dev: true 318 | 319 | /@babel/helper-wrap-function/7.19.0: 320 | resolution: {integrity: sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==} 321 | engines: {node: '>=6.9.0'} 322 | dependencies: 323 | '@babel/helper-function-name': 7.19.0 324 | '@babel/template': 7.18.10 325 | '@babel/traverse': 7.19.4 326 | '@babel/types': 7.19.4 327 | transitivePeerDependencies: 328 | - supports-color 329 | dev: true 330 | 331 | /@babel/helpers/7.19.4: 332 | resolution: {integrity: sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==} 333 | engines: {node: '>=6.9.0'} 334 | dependencies: 335 | '@babel/template': 7.18.10 336 | '@babel/traverse': 7.19.4 337 | '@babel/types': 7.19.4 338 | transitivePeerDependencies: 339 | - supports-color 340 | dev: true 341 | 342 | /@babel/highlight/7.18.6: 343 | resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} 344 | engines: {node: '>=6.9.0'} 345 | dependencies: 346 | '@babel/helper-validator-identifier': 7.19.1 347 | chalk: 2.4.2 348 | js-tokens: 4.0.0 349 | dev: true 350 | 351 | /@babel/parser/7.19.4: 352 | resolution: {integrity: sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==} 353 | engines: {node: '>=6.0.0'} 354 | hasBin: true 355 | dependencies: 356 | '@babel/types': 7.19.4 357 | dev: true 358 | 359 | /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.19.3: 360 | resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} 361 | engines: {node: '>=6.9.0'} 362 | peerDependencies: 363 | '@babel/core': ^7.0.0 364 | dependencies: 365 | '@babel/core': 7.19.3 366 | '@babel/helper-plugin-utils': 7.19.0 367 | dev: true 368 | 369 | /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.18.9_@babel+core@7.19.3: 370 | resolution: {integrity: sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==} 371 | engines: {node: '>=6.9.0'} 372 | peerDependencies: 373 | '@babel/core': ^7.13.0 374 | dependencies: 375 | '@babel/core': 7.19.3 376 | '@babel/helper-plugin-utils': 7.19.0 377 | '@babel/helper-skip-transparent-expression-wrappers': 7.18.9 378 | '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.19.3 379 | dev: true 380 | 381 | /@babel/plugin-proposal-async-generator-functions/7.19.1_@babel+core@7.19.3: 382 | resolution: {integrity: sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q==} 383 | engines: {node: '>=6.9.0'} 384 | peerDependencies: 385 | '@babel/core': ^7.0.0-0 386 | dependencies: 387 | '@babel/core': 7.19.3 388 | '@babel/helper-environment-visitor': 7.18.9 389 | '@babel/helper-plugin-utils': 7.19.0 390 | '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.19.3 391 | '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.19.3 392 | transitivePeerDependencies: 393 | - supports-color 394 | dev: true 395 | 396 | /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.19.3: 397 | resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} 398 | engines: {node: '>=6.9.0'} 399 | peerDependencies: 400 | '@babel/core': ^7.0.0-0 401 | dependencies: 402 | '@babel/core': 7.19.3 403 | '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.3 404 | '@babel/helper-plugin-utils': 7.19.0 405 | transitivePeerDependencies: 406 | - supports-color 407 | dev: true 408 | 409 | /@babel/plugin-proposal-class-static-block/7.18.6_@babel+core@7.19.3: 410 | resolution: {integrity: sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==} 411 | engines: {node: '>=6.9.0'} 412 | peerDependencies: 413 | '@babel/core': ^7.12.0 414 | dependencies: 415 | '@babel/core': 7.19.3 416 | '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.3 417 | '@babel/helper-plugin-utils': 7.19.0 418 | '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.19.3 419 | transitivePeerDependencies: 420 | - supports-color 421 | dev: true 422 | 423 | /@babel/plugin-proposal-dynamic-import/7.18.6_@babel+core@7.19.3: 424 | resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} 425 | engines: {node: '>=6.9.0'} 426 | peerDependencies: 427 | '@babel/core': ^7.0.0-0 428 | dependencies: 429 | '@babel/core': 7.19.3 430 | '@babel/helper-plugin-utils': 7.19.0 431 | '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.19.3 432 | dev: true 433 | 434 | /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.19.3: 435 | resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} 436 | engines: {node: '>=6.9.0'} 437 | peerDependencies: 438 | '@babel/core': ^7.0.0-0 439 | dependencies: 440 | '@babel/core': 7.19.3 441 | '@babel/helper-plugin-utils': 7.19.0 442 | '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.19.3 443 | dev: true 444 | 445 | /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.19.3: 446 | resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} 447 | engines: {node: '>=6.9.0'} 448 | peerDependencies: 449 | '@babel/core': ^7.0.0-0 450 | dependencies: 451 | '@babel/core': 7.19.3 452 | '@babel/helper-plugin-utils': 7.19.0 453 | '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.19.3 454 | dev: true 455 | 456 | /@babel/plugin-proposal-logical-assignment-operators/7.18.9_@babel+core@7.19.3: 457 | resolution: {integrity: sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==} 458 | engines: {node: '>=6.9.0'} 459 | peerDependencies: 460 | '@babel/core': ^7.0.0-0 461 | dependencies: 462 | '@babel/core': 7.19.3 463 | '@babel/helper-plugin-utils': 7.19.0 464 | '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.19.3 465 | dev: true 466 | 467 | /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.19.3: 468 | resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} 469 | engines: {node: '>=6.9.0'} 470 | peerDependencies: 471 | '@babel/core': ^7.0.0-0 472 | dependencies: 473 | '@babel/core': 7.19.3 474 | '@babel/helper-plugin-utils': 7.19.0 475 | '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.19.3 476 | dev: true 477 | 478 | /@babel/plugin-proposal-numeric-separator/7.18.6_@babel+core@7.19.3: 479 | resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} 480 | engines: {node: '>=6.9.0'} 481 | peerDependencies: 482 | '@babel/core': ^7.0.0-0 483 | dependencies: 484 | '@babel/core': 7.19.3 485 | '@babel/helper-plugin-utils': 7.19.0 486 | '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.19.3 487 | dev: true 488 | 489 | /@babel/plugin-proposal-object-rest-spread/7.19.4_@babel+core@7.19.3: 490 | resolution: {integrity: sha512-wHmj6LDxVDnL+3WhXteUBaoM1aVILZODAUjg11kHqG4cOlfgMQGxw6aCgvrXrmaJR3Bn14oZhImyCPZzRpC93Q==} 491 | engines: {node: '>=6.9.0'} 492 | peerDependencies: 493 | '@babel/core': ^7.0.0-0 494 | dependencies: 495 | '@babel/compat-data': 7.19.4 496 | '@babel/core': 7.19.3 497 | '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.3 498 | '@babel/helper-plugin-utils': 7.19.0 499 | '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.19.3 500 | '@babel/plugin-transform-parameters': 7.18.8_@babel+core@7.19.3 501 | dev: true 502 | 503 | /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.19.3: 504 | resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} 505 | engines: {node: '>=6.9.0'} 506 | peerDependencies: 507 | '@babel/core': ^7.0.0-0 508 | dependencies: 509 | '@babel/core': 7.19.3 510 | '@babel/helper-plugin-utils': 7.19.0 511 | '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.19.3 512 | dev: true 513 | 514 | /@babel/plugin-proposal-optional-chaining/7.18.9_@babel+core@7.19.3: 515 | resolution: {integrity: sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==} 516 | engines: {node: '>=6.9.0'} 517 | peerDependencies: 518 | '@babel/core': ^7.0.0-0 519 | dependencies: 520 | '@babel/core': 7.19.3 521 | '@babel/helper-plugin-utils': 7.19.0 522 | '@babel/helper-skip-transparent-expression-wrappers': 7.18.9 523 | '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.19.3 524 | dev: true 525 | 526 | /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.19.3: 527 | resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} 528 | engines: {node: '>=6.9.0'} 529 | peerDependencies: 530 | '@babel/core': ^7.0.0-0 531 | dependencies: 532 | '@babel/core': 7.19.3 533 | '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.3 534 | '@babel/helper-plugin-utils': 7.19.0 535 | transitivePeerDependencies: 536 | - supports-color 537 | dev: true 538 | 539 | /@babel/plugin-proposal-private-property-in-object/7.18.6_@babel+core@7.19.3: 540 | resolution: {integrity: sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==} 541 | engines: {node: '>=6.9.0'} 542 | peerDependencies: 543 | '@babel/core': ^7.0.0-0 544 | dependencies: 545 | '@babel/core': 7.19.3 546 | '@babel/helper-annotate-as-pure': 7.18.6 547 | '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.3 548 | '@babel/helper-plugin-utils': 7.19.0 549 | '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.19.3 550 | transitivePeerDependencies: 551 | - supports-color 552 | dev: true 553 | 554 | /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.19.3: 555 | resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} 556 | engines: {node: '>=4'} 557 | peerDependencies: 558 | '@babel/core': ^7.0.0-0 559 | dependencies: 560 | '@babel/core': 7.19.3 561 | '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.19.3 562 | '@babel/helper-plugin-utils': 7.19.0 563 | dev: true 564 | 565 | /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.19.3: 566 | resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} 567 | peerDependencies: 568 | '@babel/core': ^7.0.0-0 569 | dependencies: 570 | '@babel/core': 7.19.3 571 | '@babel/helper-plugin-utils': 7.19.0 572 | dev: true 573 | 574 | /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.19.3: 575 | resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} 576 | peerDependencies: 577 | '@babel/core': ^7.0.0-0 578 | dependencies: 579 | '@babel/core': 7.19.3 580 | '@babel/helper-plugin-utils': 7.19.0 581 | dev: true 582 | 583 | /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.19.3: 584 | resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} 585 | engines: {node: '>=6.9.0'} 586 | peerDependencies: 587 | '@babel/core': ^7.0.0-0 588 | dependencies: 589 | '@babel/core': 7.19.3 590 | '@babel/helper-plugin-utils': 7.19.0 591 | dev: true 592 | 593 | /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.19.3: 594 | resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} 595 | peerDependencies: 596 | '@babel/core': ^7.0.0-0 597 | dependencies: 598 | '@babel/core': 7.19.3 599 | '@babel/helper-plugin-utils': 7.19.0 600 | dev: true 601 | 602 | /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.19.3: 603 | resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} 604 | peerDependencies: 605 | '@babel/core': ^7.0.0-0 606 | dependencies: 607 | '@babel/core': 7.19.3 608 | '@babel/helper-plugin-utils': 7.19.0 609 | dev: true 610 | 611 | /@babel/plugin-syntax-import-assertions/7.18.6_@babel+core@7.19.3: 612 | resolution: {integrity: sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==} 613 | engines: {node: '>=6.9.0'} 614 | peerDependencies: 615 | '@babel/core': ^7.0.0-0 616 | dependencies: 617 | '@babel/core': 7.19.3 618 | '@babel/helper-plugin-utils': 7.19.0 619 | dev: true 620 | 621 | /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.19.3: 622 | resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} 623 | peerDependencies: 624 | '@babel/core': ^7.0.0-0 625 | dependencies: 626 | '@babel/core': 7.19.3 627 | '@babel/helper-plugin-utils': 7.19.0 628 | dev: true 629 | 630 | /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.19.3: 631 | resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} 632 | peerDependencies: 633 | '@babel/core': ^7.0.0-0 634 | dependencies: 635 | '@babel/core': 7.19.3 636 | '@babel/helper-plugin-utils': 7.19.0 637 | dev: true 638 | 639 | /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.19.3: 640 | resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} 641 | peerDependencies: 642 | '@babel/core': ^7.0.0-0 643 | dependencies: 644 | '@babel/core': 7.19.3 645 | '@babel/helper-plugin-utils': 7.19.0 646 | dev: true 647 | 648 | /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.19.3: 649 | resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} 650 | peerDependencies: 651 | '@babel/core': ^7.0.0-0 652 | dependencies: 653 | '@babel/core': 7.19.3 654 | '@babel/helper-plugin-utils': 7.19.0 655 | dev: true 656 | 657 | /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.19.3: 658 | resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} 659 | peerDependencies: 660 | '@babel/core': ^7.0.0-0 661 | dependencies: 662 | '@babel/core': 7.19.3 663 | '@babel/helper-plugin-utils': 7.19.0 664 | dev: true 665 | 666 | /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.19.3: 667 | resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} 668 | peerDependencies: 669 | '@babel/core': ^7.0.0-0 670 | dependencies: 671 | '@babel/core': 7.19.3 672 | '@babel/helper-plugin-utils': 7.19.0 673 | dev: true 674 | 675 | /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.19.3: 676 | resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} 677 | peerDependencies: 678 | '@babel/core': ^7.0.0-0 679 | dependencies: 680 | '@babel/core': 7.19.3 681 | '@babel/helper-plugin-utils': 7.19.0 682 | dev: true 683 | 684 | /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.19.3: 685 | resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} 686 | engines: {node: '>=6.9.0'} 687 | peerDependencies: 688 | '@babel/core': ^7.0.0-0 689 | dependencies: 690 | '@babel/core': 7.19.3 691 | '@babel/helper-plugin-utils': 7.19.0 692 | dev: true 693 | 694 | /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.19.3: 695 | resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} 696 | engines: {node: '>=6.9.0'} 697 | peerDependencies: 698 | '@babel/core': ^7.0.0-0 699 | dependencies: 700 | '@babel/core': 7.19.3 701 | '@babel/helper-plugin-utils': 7.19.0 702 | dev: true 703 | 704 | /@babel/plugin-syntax-typescript/7.18.6_@babel+core@7.19.3: 705 | resolution: {integrity: sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==} 706 | engines: {node: '>=6.9.0'} 707 | peerDependencies: 708 | '@babel/core': ^7.0.0-0 709 | dependencies: 710 | '@babel/core': 7.19.3 711 | '@babel/helper-plugin-utils': 7.19.0 712 | dev: true 713 | 714 | /@babel/plugin-transform-arrow-functions/7.18.6_@babel+core@7.19.3: 715 | resolution: {integrity: sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==} 716 | engines: {node: '>=6.9.0'} 717 | peerDependencies: 718 | '@babel/core': ^7.0.0-0 719 | dependencies: 720 | '@babel/core': 7.19.3 721 | '@babel/helper-plugin-utils': 7.19.0 722 | dev: true 723 | 724 | /@babel/plugin-transform-async-to-generator/7.18.6_@babel+core@7.19.3: 725 | resolution: {integrity: sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==} 726 | engines: {node: '>=6.9.0'} 727 | peerDependencies: 728 | '@babel/core': ^7.0.0-0 729 | dependencies: 730 | '@babel/core': 7.19.3 731 | '@babel/helper-module-imports': 7.18.6 732 | '@babel/helper-plugin-utils': 7.19.0 733 | '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.19.3 734 | transitivePeerDependencies: 735 | - supports-color 736 | dev: true 737 | 738 | /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.19.3: 739 | resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} 740 | engines: {node: '>=6.9.0'} 741 | peerDependencies: 742 | '@babel/core': ^7.0.0-0 743 | dependencies: 744 | '@babel/core': 7.19.3 745 | '@babel/helper-plugin-utils': 7.19.0 746 | dev: true 747 | 748 | /@babel/plugin-transform-block-scoping/7.19.4_@babel+core@7.19.3: 749 | resolution: {integrity: sha512-934S2VLLlt2hRJwPf4MczaOr4hYF0z+VKPwqTNxyKX7NthTiPfhuKFWQZHXRM0vh/wo/VyXB3s4bZUNA08l+tQ==} 750 | engines: {node: '>=6.9.0'} 751 | peerDependencies: 752 | '@babel/core': ^7.0.0-0 753 | dependencies: 754 | '@babel/core': 7.19.3 755 | '@babel/helper-plugin-utils': 7.19.0 756 | dev: true 757 | 758 | /@babel/plugin-transform-classes/7.19.0_@babel+core@7.19.3: 759 | resolution: {integrity: sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==} 760 | engines: {node: '>=6.9.0'} 761 | peerDependencies: 762 | '@babel/core': ^7.0.0-0 763 | dependencies: 764 | '@babel/core': 7.19.3 765 | '@babel/helper-annotate-as-pure': 7.18.6 766 | '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.3 767 | '@babel/helper-environment-visitor': 7.18.9 768 | '@babel/helper-function-name': 7.19.0 769 | '@babel/helper-optimise-call-expression': 7.18.6 770 | '@babel/helper-plugin-utils': 7.19.0 771 | '@babel/helper-replace-supers': 7.19.1 772 | '@babel/helper-split-export-declaration': 7.18.6 773 | globals: 11.12.0 774 | transitivePeerDependencies: 775 | - supports-color 776 | dev: true 777 | 778 | /@babel/plugin-transform-computed-properties/7.18.9_@babel+core@7.19.3: 779 | resolution: {integrity: sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==} 780 | engines: {node: '>=6.9.0'} 781 | peerDependencies: 782 | '@babel/core': ^7.0.0-0 783 | dependencies: 784 | '@babel/core': 7.19.3 785 | '@babel/helper-plugin-utils': 7.19.0 786 | dev: true 787 | 788 | /@babel/plugin-transform-destructuring/7.19.4_@babel+core@7.19.3: 789 | resolution: {integrity: sha512-t0j0Hgidqf0aM86dF8U+vXYReUgJnlv4bZLsyoPnwZNrGY+7/38o8YjaELrvHeVfTZao15kjR0PVv0nju2iduA==} 790 | engines: {node: '>=6.9.0'} 791 | peerDependencies: 792 | '@babel/core': ^7.0.0-0 793 | dependencies: 794 | '@babel/core': 7.19.3 795 | '@babel/helper-plugin-utils': 7.19.0 796 | dev: true 797 | 798 | /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.19.3: 799 | resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} 800 | engines: {node: '>=6.9.0'} 801 | peerDependencies: 802 | '@babel/core': ^7.0.0-0 803 | dependencies: 804 | '@babel/core': 7.19.3 805 | '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.19.3 806 | '@babel/helper-plugin-utils': 7.19.0 807 | dev: true 808 | 809 | /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.19.3: 810 | resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} 811 | engines: {node: '>=6.9.0'} 812 | peerDependencies: 813 | '@babel/core': ^7.0.0-0 814 | dependencies: 815 | '@babel/core': 7.19.3 816 | '@babel/helper-plugin-utils': 7.19.0 817 | dev: true 818 | 819 | /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.19.3: 820 | resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} 821 | engines: {node: '>=6.9.0'} 822 | peerDependencies: 823 | '@babel/core': ^7.0.0-0 824 | dependencies: 825 | '@babel/core': 7.19.3 826 | '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 827 | '@babel/helper-plugin-utils': 7.19.0 828 | dev: true 829 | 830 | /@babel/plugin-transform-for-of/7.18.8_@babel+core@7.19.3: 831 | resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} 832 | engines: {node: '>=6.9.0'} 833 | peerDependencies: 834 | '@babel/core': ^7.0.0-0 835 | dependencies: 836 | '@babel/core': 7.19.3 837 | '@babel/helper-plugin-utils': 7.19.0 838 | dev: true 839 | 840 | /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.19.3: 841 | resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} 842 | engines: {node: '>=6.9.0'} 843 | peerDependencies: 844 | '@babel/core': ^7.0.0-0 845 | dependencies: 846 | '@babel/core': 7.19.3 847 | '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.3 848 | '@babel/helper-function-name': 7.19.0 849 | '@babel/helper-plugin-utils': 7.19.0 850 | dev: true 851 | 852 | /@babel/plugin-transform-literals/7.18.9_@babel+core@7.19.3: 853 | resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} 854 | engines: {node: '>=6.9.0'} 855 | peerDependencies: 856 | '@babel/core': ^7.0.0-0 857 | dependencies: 858 | '@babel/core': 7.19.3 859 | '@babel/helper-plugin-utils': 7.19.0 860 | dev: true 861 | 862 | /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.19.3: 863 | resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} 864 | engines: {node: '>=6.9.0'} 865 | peerDependencies: 866 | '@babel/core': ^7.0.0-0 867 | dependencies: 868 | '@babel/core': 7.19.3 869 | '@babel/helper-plugin-utils': 7.19.0 870 | dev: true 871 | 872 | /@babel/plugin-transform-modules-amd/7.18.6_@babel+core@7.19.3: 873 | resolution: {integrity: sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==} 874 | engines: {node: '>=6.9.0'} 875 | peerDependencies: 876 | '@babel/core': ^7.0.0-0 877 | dependencies: 878 | '@babel/core': 7.19.3 879 | '@babel/helper-module-transforms': 7.19.0 880 | '@babel/helper-plugin-utils': 7.19.0 881 | babel-plugin-dynamic-import-node: 2.3.3 882 | transitivePeerDependencies: 883 | - supports-color 884 | dev: true 885 | 886 | /@babel/plugin-transform-modules-commonjs/7.18.6_@babel+core@7.19.3: 887 | resolution: {integrity: sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==} 888 | engines: {node: '>=6.9.0'} 889 | peerDependencies: 890 | '@babel/core': ^7.0.0-0 891 | dependencies: 892 | '@babel/core': 7.19.3 893 | '@babel/helper-module-transforms': 7.19.0 894 | '@babel/helper-plugin-utils': 7.19.0 895 | '@babel/helper-simple-access': 7.19.4 896 | babel-plugin-dynamic-import-node: 2.3.3 897 | transitivePeerDependencies: 898 | - supports-color 899 | dev: true 900 | 901 | /@babel/plugin-transform-modules-systemjs/7.19.0_@babel+core@7.19.3: 902 | resolution: {integrity: sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==} 903 | engines: {node: '>=6.9.0'} 904 | peerDependencies: 905 | '@babel/core': ^7.0.0-0 906 | dependencies: 907 | '@babel/core': 7.19.3 908 | '@babel/helper-hoist-variables': 7.18.6 909 | '@babel/helper-module-transforms': 7.19.0 910 | '@babel/helper-plugin-utils': 7.19.0 911 | '@babel/helper-validator-identifier': 7.19.1 912 | babel-plugin-dynamic-import-node: 2.3.3 913 | transitivePeerDependencies: 914 | - supports-color 915 | dev: true 916 | 917 | /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.19.3: 918 | resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} 919 | engines: {node: '>=6.9.0'} 920 | peerDependencies: 921 | '@babel/core': ^7.0.0-0 922 | dependencies: 923 | '@babel/core': 7.19.3 924 | '@babel/helper-module-transforms': 7.19.0 925 | '@babel/helper-plugin-utils': 7.19.0 926 | transitivePeerDependencies: 927 | - supports-color 928 | dev: true 929 | 930 | /@babel/plugin-transform-named-capturing-groups-regex/7.19.1_@babel+core@7.19.3: 931 | resolution: {integrity: sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==} 932 | engines: {node: '>=6.9.0'} 933 | peerDependencies: 934 | '@babel/core': ^7.0.0 935 | dependencies: 936 | '@babel/core': 7.19.3 937 | '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.19.3 938 | '@babel/helper-plugin-utils': 7.19.0 939 | dev: true 940 | 941 | /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.19.3: 942 | resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} 943 | engines: {node: '>=6.9.0'} 944 | peerDependencies: 945 | '@babel/core': ^7.0.0-0 946 | dependencies: 947 | '@babel/core': 7.19.3 948 | '@babel/helper-plugin-utils': 7.19.0 949 | dev: true 950 | 951 | /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.19.3: 952 | resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} 953 | engines: {node: '>=6.9.0'} 954 | peerDependencies: 955 | '@babel/core': ^7.0.0-0 956 | dependencies: 957 | '@babel/core': 7.19.3 958 | '@babel/helper-plugin-utils': 7.19.0 959 | '@babel/helper-replace-supers': 7.19.1 960 | transitivePeerDependencies: 961 | - supports-color 962 | dev: true 963 | 964 | /@babel/plugin-transform-parameters/7.18.8_@babel+core@7.19.3: 965 | resolution: {integrity: sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==} 966 | engines: {node: '>=6.9.0'} 967 | peerDependencies: 968 | '@babel/core': ^7.0.0-0 969 | dependencies: 970 | '@babel/core': 7.19.3 971 | '@babel/helper-plugin-utils': 7.19.0 972 | dev: true 973 | 974 | /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.19.3: 975 | resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} 976 | engines: {node: '>=6.9.0'} 977 | peerDependencies: 978 | '@babel/core': ^7.0.0-0 979 | dependencies: 980 | '@babel/core': 7.19.3 981 | '@babel/helper-plugin-utils': 7.19.0 982 | dev: true 983 | 984 | /@babel/plugin-transform-regenerator/7.18.6_@babel+core@7.19.3: 985 | resolution: {integrity: sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==} 986 | engines: {node: '>=6.9.0'} 987 | peerDependencies: 988 | '@babel/core': ^7.0.0-0 989 | dependencies: 990 | '@babel/core': 7.19.3 991 | '@babel/helper-plugin-utils': 7.19.0 992 | regenerator-transform: 0.15.0 993 | dev: true 994 | 995 | /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.19.3: 996 | resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} 997 | engines: {node: '>=6.9.0'} 998 | peerDependencies: 999 | '@babel/core': ^7.0.0-0 1000 | dependencies: 1001 | '@babel/core': 7.19.3 1002 | '@babel/helper-plugin-utils': 7.19.0 1003 | dev: true 1004 | 1005 | /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.19.3: 1006 | resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} 1007 | engines: {node: '>=6.9.0'} 1008 | peerDependencies: 1009 | '@babel/core': ^7.0.0-0 1010 | dependencies: 1011 | '@babel/core': 7.19.3 1012 | '@babel/helper-plugin-utils': 7.19.0 1013 | dev: true 1014 | 1015 | /@babel/plugin-transform-spread/7.19.0_@babel+core@7.19.3: 1016 | resolution: {integrity: sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==} 1017 | engines: {node: '>=6.9.0'} 1018 | peerDependencies: 1019 | '@babel/core': ^7.0.0-0 1020 | dependencies: 1021 | '@babel/core': 7.19.3 1022 | '@babel/helper-plugin-utils': 7.19.0 1023 | '@babel/helper-skip-transparent-expression-wrappers': 7.18.9 1024 | dev: true 1025 | 1026 | /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.19.3: 1027 | resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} 1028 | engines: {node: '>=6.9.0'} 1029 | peerDependencies: 1030 | '@babel/core': ^7.0.0-0 1031 | dependencies: 1032 | '@babel/core': 7.19.3 1033 | '@babel/helper-plugin-utils': 7.19.0 1034 | dev: true 1035 | 1036 | /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.19.3: 1037 | resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} 1038 | engines: {node: '>=6.9.0'} 1039 | peerDependencies: 1040 | '@babel/core': ^7.0.0-0 1041 | dependencies: 1042 | '@babel/core': 7.19.3 1043 | '@babel/helper-plugin-utils': 7.19.0 1044 | dev: true 1045 | 1046 | /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.19.3: 1047 | resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} 1048 | engines: {node: '>=6.9.0'} 1049 | peerDependencies: 1050 | '@babel/core': ^7.0.0-0 1051 | dependencies: 1052 | '@babel/core': 7.19.3 1053 | '@babel/helper-plugin-utils': 7.19.0 1054 | dev: true 1055 | 1056 | /@babel/plugin-transform-typescript/7.19.3_@babel+core@7.19.3: 1057 | resolution: {integrity: sha512-z6fnuK9ve9u/0X0rRvI9MY0xg+DOUaABDYOe+/SQTxtlptaBB/V9JIUxJn6xp3lMBeb9qe8xSFmHU35oZDXD+w==} 1058 | engines: {node: '>=6.9.0'} 1059 | peerDependencies: 1060 | '@babel/core': ^7.0.0-0 1061 | dependencies: 1062 | '@babel/core': 7.19.3 1063 | '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.3 1064 | '@babel/helper-plugin-utils': 7.19.0 1065 | '@babel/plugin-syntax-typescript': 7.18.6_@babel+core@7.19.3 1066 | transitivePeerDependencies: 1067 | - supports-color 1068 | dev: true 1069 | 1070 | /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.19.3: 1071 | resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} 1072 | engines: {node: '>=6.9.0'} 1073 | peerDependencies: 1074 | '@babel/core': ^7.0.0-0 1075 | dependencies: 1076 | '@babel/core': 7.19.3 1077 | '@babel/helper-plugin-utils': 7.19.0 1078 | dev: true 1079 | 1080 | /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.19.3: 1081 | resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} 1082 | engines: {node: '>=6.9.0'} 1083 | peerDependencies: 1084 | '@babel/core': ^7.0.0-0 1085 | dependencies: 1086 | '@babel/core': 7.19.3 1087 | '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.19.3 1088 | '@babel/helper-plugin-utils': 7.19.0 1089 | dev: true 1090 | 1091 | /@babel/preset-env/7.19.4_@babel+core@7.19.3: 1092 | resolution: {integrity: sha512-5QVOTXUdqTCjQuh2GGtdd7YEhoRXBMVGROAtsBeLGIbIz3obCBIfRMT1I3ZKkMgNzwkyCkftDXSSkHxnfVf4qg==} 1093 | engines: {node: '>=6.9.0'} 1094 | peerDependencies: 1095 | '@babel/core': ^7.0.0-0 1096 | dependencies: 1097 | '@babel/compat-data': 7.19.4 1098 | '@babel/core': 7.19.3 1099 | '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.3 1100 | '@babel/helper-plugin-utils': 7.19.0 1101 | '@babel/helper-validator-option': 7.18.6 1102 | '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6_@babel+core@7.19.3 1103 | '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9_@babel+core@7.19.3 1104 | '@babel/plugin-proposal-async-generator-functions': 7.19.1_@babel+core@7.19.3 1105 | '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.19.3 1106 | '@babel/plugin-proposal-class-static-block': 7.18.6_@babel+core@7.19.3 1107 | '@babel/plugin-proposal-dynamic-import': 7.18.6_@babel+core@7.19.3 1108 | '@babel/plugin-proposal-export-namespace-from': 7.18.9_@babel+core@7.19.3 1109 | '@babel/plugin-proposal-json-strings': 7.18.6_@babel+core@7.19.3 1110 | '@babel/plugin-proposal-logical-assignment-operators': 7.18.9_@babel+core@7.19.3 1111 | '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.19.3 1112 | '@babel/plugin-proposal-numeric-separator': 7.18.6_@babel+core@7.19.3 1113 | '@babel/plugin-proposal-object-rest-spread': 7.19.4_@babel+core@7.19.3 1114 | '@babel/plugin-proposal-optional-catch-binding': 7.18.6_@babel+core@7.19.3 1115 | '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.19.3 1116 | '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.19.3 1117 | '@babel/plugin-proposal-private-property-in-object': 7.18.6_@babel+core@7.19.3 1118 | '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.19.3 1119 | '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.19.3 1120 | '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.19.3 1121 | '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.19.3 1122 | '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.19.3 1123 | '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.19.3 1124 | '@babel/plugin-syntax-import-assertions': 7.18.6_@babel+core@7.19.3 1125 | '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.19.3 1126 | '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.19.3 1127 | '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.19.3 1128 | '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.19.3 1129 | '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.19.3 1130 | '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.19.3 1131 | '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.19.3 1132 | '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.19.3 1133 | '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.19.3 1134 | '@babel/plugin-transform-arrow-functions': 7.18.6_@babel+core@7.19.3 1135 | '@babel/plugin-transform-async-to-generator': 7.18.6_@babel+core@7.19.3 1136 | '@babel/plugin-transform-block-scoped-functions': 7.18.6_@babel+core@7.19.3 1137 | '@babel/plugin-transform-block-scoping': 7.19.4_@babel+core@7.19.3 1138 | '@babel/plugin-transform-classes': 7.19.0_@babel+core@7.19.3 1139 | '@babel/plugin-transform-computed-properties': 7.18.9_@babel+core@7.19.3 1140 | '@babel/plugin-transform-destructuring': 7.19.4_@babel+core@7.19.3 1141 | '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.19.3 1142 | '@babel/plugin-transform-duplicate-keys': 7.18.9_@babel+core@7.19.3 1143 | '@babel/plugin-transform-exponentiation-operator': 7.18.6_@babel+core@7.19.3 1144 | '@babel/plugin-transform-for-of': 7.18.8_@babel+core@7.19.3 1145 | '@babel/plugin-transform-function-name': 7.18.9_@babel+core@7.19.3 1146 | '@babel/plugin-transform-literals': 7.18.9_@babel+core@7.19.3 1147 | '@babel/plugin-transform-member-expression-literals': 7.18.6_@babel+core@7.19.3 1148 | '@babel/plugin-transform-modules-amd': 7.18.6_@babel+core@7.19.3 1149 | '@babel/plugin-transform-modules-commonjs': 7.18.6_@babel+core@7.19.3 1150 | '@babel/plugin-transform-modules-systemjs': 7.19.0_@babel+core@7.19.3 1151 | '@babel/plugin-transform-modules-umd': 7.18.6_@babel+core@7.19.3 1152 | '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1_@babel+core@7.19.3 1153 | '@babel/plugin-transform-new-target': 7.18.6_@babel+core@7.19.3 1154 | '@babel/plugin-transform-object-super': 7.18.6_@babel+core@7.19.3 1155 | '@babel/plugin-transform-parameters': 7.18.8_@babel+core@7.19.3 1156 | '@babel/plugin-transform-property-literals': 7.18.6_@babel+core@7.19.3 1157 | '@babel/plugin-transform-regenerator': 7.18.6_@babel+core@7.19.3 1158 | '@babel/plugin-transform-reserved-words': 7.18.6_@babel+core@7.19.3 1159 | '@babel/plugin-transform-shorthand-properties': 7.18.6_@babel+core@7.19.3 1160 | '@babel/plugin-transform-spread': 7.19.0_@babel+core@7.19.3 1161 | '@babel/plugin-transform-sticky-regex': 7.18.6_@babel+core@7.19.3 1162 | '@babel/plugin-transform-template-literals': 7.18.9_@babel+core@7.19.3 1163 | '@babel/plugin-transform-typeof-symbol': 7.18.9_@babel+core@7.19.3 1164 | '@babel/plugin-transform-unicode-escapes': 7.18.10_@babel+core@7.19.3 1165 | '@babel/plugin-transform-unicode-regex': 7.18.6_@babel+core@7.19.3 1166 | '@babel/preset-modules': 0.1.5_@babel+core@7.19.3 1167 | '@babel/types': 7.19.4 1168 | babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.19.3 1169 | babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.19.3 1170 | babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.19.3 1171 | core-js-compat: 3.25.5 1172 | semver: 6.3.0 1173 | transitivePeerDependencies: 1174 | - supports-color 1175 | dev: true 1176 | 1177 | /@babel/preset-modules/0.1.5_@babel+core@7.19.3: 1178 | resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} 1179 | peerDependencies: 1180 | '@babel/core': ^7.0.0-0 1181 | dependencies: 1182 | '@babel/core': 7.19.3 1183 | '@babel/helper-plugin-utils': 7.19.0 1184 | '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.19.3 1185 | '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.19.3 1186 | '@babel/types': 7.19.4 1187 | esutils: 2.0.3 1188 | dev: true 1189 | 1190 | /@babel/preset-typescript/7.18.6_@babel+core@7.19.3: 1191 | resolution: {integrity: sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==} 1192 | engines: {node: '>=6.9.0'} 1193 | peerDependencies: 1194 | '@babel/core': ^7.0.0-0 1195 | dependencies: 1196 | '@babel/core': 7.19.3 1197 | '@babel/helper-plugin-utils': 7.19.0 1198 | '@babel/helper-validator-option': 7.18.6 1199 | '@babel/plugin-transform-typescript': 7.19.3_@babel+core@7.19.3 1200 | transitivePeerDependencies: 1201 | - supports-color 1202 | dev: true 1203 | 1204 | /@babel/runtime/7.19.4: 1205 | resolution: {integrity: sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==} 1206 | engines: {node: '>=6.9.0'} 1207 | dependencies: 1208 | regenerator-runtime: 0.13.10 1209 | dev: true 1210 | 1211 | /@babel/template/7.18.10: 1212 | resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} 1213 | engines: {node: '>=6.9.0'} 1214 | dependencies: 1215 | '@babel/code-frame': 7.18.6 1216 | '@babel/parser': 7.19.4 1217 | '@babel/types': 7.19.4 1218 | dev: true 1219 | 1220 | /@babel/traverse/7.19.4: 1221 | resolution: {integrity: sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==} 1222 | engines: {node: '>=6.9.0'} 1223 | dependencies: 1224 | '@babel/code-frame': 7.18.6 1225 | '@babel/generator': 7.19.5 1226 | '@babel/helper-environment-visitor': 7.18.9 1227 | '@babel/helper-function-name': 7.19.0 1228 | '@babel/helper-hoist-variables': 7.18.6 1229 | '@babel/helper-split-export-declaration': 7.18.6 1230 | '@babel/parser': 7.19.4 1231 | '@babel/types': 7.19.4 1232 | debug: 4.3.4 1233 | globals: 11.12.0 1234 | transitivePeerDependencies: 1235 | - supports-color 1236 | dev: true 1237 | 1238 | /@babel/types/7.19.4: 1239 | resolution: {integrity: sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==} 1240 | engines: {node: '>=6.9.0'} 1241 | dependencies: 1242 | '@babel/helper-string-parser': 7.19.4 1243 | '@babel/helper-validator-identifier': 7.19.1 1244 | to-fast-properties: 2.0.0 1245 | dev: true 1246 | 1247 | /@esbuild/android-arm/0.15.11: 1248 | resolution: {integrity: sha512-PzMcQLazLBkwDEkrNPi9AbjFt6+3I7HKbiYF2XtWQ7wItrHvEOeO3T8Am434zAozWtVP7lrTue1bEfc2nYWeCA==} 1249 | engines: {node: '>=12'} 1250 | cpu: [arm] 1251 | os: [android] 1252 | requiresBuild: true 1253 | dev: true 1254 | optional: true 1255 | 1256 | /@esbuild/linux-loong64/0.15.11: 1257 | resolution: {integrity: sha512-geWp637tUhNmhL3Xgy4Bj703yXB9dqiLJe05lCUfjSFDrQf9C/8pArusyPUbUbPwlC/EAUjBw32sxuIl/11dZw==} 1258 | engines: {node: '>=12'} 1259 | cpu: [loong64] 1260 | os: [linux] 1261 | requiresBuild: true 1262 | dev: true 1263 | optional: true 1264 | 1265 | /@jridgewell/gen-mapping/0.1.1: 1266 | resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} 1267 | engines: {node: '>=6.0.0'} 1268 | dependencies: 1269 | '@jridgewell/set-array': 1.1.2 1270 | '@jridgewell/sourcemap-codec': 1.4.14 1271 | dev: true 1272 | 1273 | /@jridgewell/gen-mapping/0.3.2: 1274 | resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} 1275 | engines: {node: '>=6.0.0'} 1276 | dependencies: 1277 | '@jridgewell/set-array': 1.1.2 1278 | '@jridgewell/sourcemap-codec': 1.4.14 1279 | '@jridgewell/trace-mapping': 0.3.17 1280 | dev: true 1281 | 1282 | /@jridgewell/resolve-uri/3.1.0: 1283 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} 1284 | engines: {node: '>=6.0.0'} 1285 | dev: true 1286 | 1287 | /@jridgewell/set-array/1.1.2: 1288 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} 1289 | engines: {node: '>=6.0.0'} 1290 | dev: true 1291 | 1292 | /@jridgewell/sourcemap-codec/1.4.14: 1293 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 1294 | dev: true 1295 | 1296 | /@jridgewell/trace-mapping/0.3.17: 1297 | resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} 1298 | dependencies: 1299 | '@jridgewell/resolve-uri': 3.1.0 1300 | '@jridgewell/sourcemap-codec': 1.4.14 1301 | dev: true 1302 | 1303 | /@rollup/plugin-typescript/8.5.0_hafrwlgfjmvsm7253l3bfjzhnq: 1304 | resolution: {integrity: sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==} 1305 | engines: {node: '>=8.0.0'} 1306 | peerDependencies: 1307 | rollup: ^2.14.0 1308 | tslib: '*' 1309 | typescript: '>=3.7.0' 1310 | peerDependenciesMeta: 1311 | tslib: 1312 | optional: true 1313 | dependencies: 1314 | '@rollup/pluginutils': 3.1.0_rollup@2.79.1 1315 | resolve: 1.22.1 1316 | rollup: 2.79.1 1317 | tslib: 2.4.0 1318 | typescript: 4.8.4 1319 | dev: true 1320 | 1321 | /@rollup/pluginutils/3.1.0_rollup@2.79.1: 1322 | resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} 1323 | engines: {node: '>= 8.0.0'} 1324 | peerDependencies: 1325 | rollup: ^1.20.0||^2.0.0 1326 | dependencies: 1327 | '@types/estree': 0.0.39 1328 | estree-walker: 1.0.1 1329 | picomatch: 2.3.1 1330 | rollup: 2.79.1 1331 | dev: true 1332 | 1333 | /@types/chai-subset/1.3.3: 1334 | resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} 1335 | dependencies: 1336 | '@types/chai': 4.3.3 1337 | dev: true 1338 | 1339 | /@types/chai/4.3.3: 1340 | resolution: {integrity: sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==} 1341 | dev: true 1342 | 1343 | /@types/estree/0.0.39: 1344 | resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} 1345 | dev: true 1346 | 1347 | /@types/node/18.11.0: 1348 | resolution: {integrity: sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==} 1349 | dev: true 1350 | 1351 | /acorn/8.8.0: 1352 | resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} 1353 | engines: {node: '>=0.4.0'} 1354 | hasBin: true 1355 | dev: true 1356 | 1357 | /ansi-styles/3.2.1: 1358 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 1359 | engines: {node: '>=4'} 1360 | dependencies: 1361 | color-convert: 1.9.3 1362 | dev: true 1363 | 1364 | /assertion-error/1.1.0: 1365 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} 1366 | dev: true 1367 | 1368 | /babel-plugin-dynamic-import-node/2.3.3: 1369 | resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==} 1370 | dependencies: 1371 | object.assign: 4.1.4 1372 | dev: true 1373 | 1374 | /babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.19.3: 1375 | resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} 1376 | peerDependencies: 1377 | '@babel/core': ^7.0.0-0 1378 | dependencies: 1379 | '@babel/compat-data': 7.19.4 1380 | '@babel/core': 7.19.3 1381 | '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.19.3 1382 | semver: 6.3.0 1383 | transitivePeerDependencies: 1384 | - supports-color 1385 | dev: true 1386 | 1387 | /babel-plugin-polyfill-corejs3/0.6.0_@babel+core@7.19.3: 1388 | resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} 1389 | peerDependencies: 1390 | '@babel/core': ^7.0.0-0 1391 | dependencies: 1392 | '@babel/core': 7.19.3 1393 | '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.19.3 1394 | core-js-compat: 3.25.5 1395 | transitivePeerDependencies: 1396 | - supports-color 1397 | dev: true 1398 | 1399 | /babel-plugin-polyfill-regenerator/0.4.1_@babel+core@7.19.3: 1400 | resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} 1401 | peerDependencies: 1402 | '@babel/core': ^7.0.0-0 1403 | dependencies: 1404 | '@babel/core': 7.19.3 1405 | '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.19.3 1406 | transitivePeerDependencies: 1407 | - supports-color 1408 | dev: true 1409 | 1410 | /browserslist/4.21.4: 1411 | resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} 1412 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 1413 | hasBin: true 1414 | dependencies: 1415 | caniuse-lite: 1.0.30001420 1416 | electron-to-chromium: 1.4.283 1417 | node-releases: 2.0.6 1418 | update-browserslist-db: 1.0.10_browserslist@4.21.4 1419 | dev: true 1420 | 1421 | /call-bind/1.0.2: 1422 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} 1423 | dependencies: 1424 | function-bind: 1.1.1 1425 | get-intrinsic: 1.1.3 1426 | dev: true 1427 | 1428 | /caniuse-lite/1.0.30001420: 1429 | resolution: {integrity: sha512-OnyeJ9ascFA9roEj72ok2Ikp7PHJTKubtEJIQ/VK3fdsS50q4KWy+Z5X0A1/GswEItKX0ctAp8n4SYDE7wTu6A==} 1430 | dev: true 1431 | 1432 | /chai/4.3.6: 1433 | resolution: {integrity: sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==} 1434 | engines: {node: '>=4'} 1435 | dependencies: 1436 | assertion-error: 1.1.0 1437 | check-error: 1.0.2 1438 | deep-eql: 3.0.1 1439 | get-func-name: 2.0.0 1440 | loupe: 2.3.4 1441 | pathval: 1.1.1 1442 | type-detect: 4.0.8 1443 | dev: true 1444 | 1445 | /chalk/2.4.2: 1446 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} 1447 | engines: {node: '>=4'} 1448 | dependencies: 1449 | ansi-styles: 3.2.1 1450 | escape-string-regexp: 1.0.5 1451 | supports-color: 5.5.0 1452 | dev: true 1453 | 1454 | /check-error/1.0.2: 1455 | resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} 1456 | dev: true 1457 | 1458 | /color-convert/1.9.3: 1459 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 1460 | dependencies: 1461 | color-name: 1.1.3 1462 | dev: true 1463 | 1464 | /color-name/1.1.3: 1465 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 1466 | dev: true 1467 | 1468 | /convert-source-map/1.9.0: 1469 | resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} 1470 | dev: true 1471 | 1472 | /core-js-compat/3.25.5: 1473 | resolution: {integrity: sha512-ovcyhs2DEBUIE0MGEKHP4olCUW/XYte3Vroyxuh38rD1wAO4dHohsovUC4eAOuzFxE6b+RXvBU3UZ9o0YhUTkA==} 1474 | dependencies: 1475 | browserslist: 4.21.4 1476 | dev: true 1477 | 1478 | /debug/4.3.4: 1479 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 1480 | engines: {node: '>=6.0'} 1481 | peerDependencies: 1482 | supports-color: '*' 1483 | peerDependenciesMeta: 1484 | supports-color: 1485 | optional: true 1486 | dependencies: 1487 | ms: 2.1.2 1488 | dev: true 1489 | 1490 | /deep-eql/3.0.1: 1491 | resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==} 1492 | engines: {node: '>=0.12'} 1493 | dependencies: 1494 | type-detect: 4.0.8 1495 | dev: true 1496 | 1497 | /define-properties/1.1.4: 1498 | resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} 1499 | engines: {node: '>= 0.4'} 1500 | dependencies: 1501 | has-property-descriptors: 1.0.0 1502 | object-keys: 1.1.1 1503 | dev: true 1504 | 1505 | /electron-to-chromium/1.4.283: 1506 | resolution: {integrity: sha512-g6RQ9zCOV+U5QVHW9OpFR7rdk/V7xfopNXnyAamdpFgCHgZ1sjI8VuR1+zG2YG/TZk+tQ8mpNkug4P8FU0fuOA==} 1507 | dev: true 1508 | 1509 | /esbuild-android-64/0.15.11: 1510 | resolution: {integrity: sha512-rrwoXEiuI1kaw4k475NJpexs8GfJqQUKcD08VR8sKHmuW9RUuTR2VxcupVvHdiGh9ihxL9m3lpqB1kju92Ialw==} 1511 | engines: {node: '>=12'} 1512 | cpu: [x64] 1513 | os: [android] 1514 | requiresBuild: true 1515 | dev: true 1516 | optional: true 1517 | 1518 | /esbuild-android-arm64/0.15.11: 1519 | resolution: {integrity: sha512-/hDubOg7BHOhUUsT8KUIU7GfZm5bihqssvqK5PfO4apag7YuObZRZSzViyEKcFn2tPeHx7RKbSBXvAopSHDZJQ==} 1520 | engines: {node: '>=12'} 1521 | cpu: [arm64] 1522 | os: [android] 1523 | requiresBuild: true 1524 | dev: true 1525 | optional: true 1526 | 1527 | /esbuild-darwin-64/0.15.11: 1528 | resolution: {integrity: sha512-1DqHD0ms3AhiwkKnjRUzmiW7JnaJJr5FKrPiR7xuyMwnjDqvNWDdMq4rKSD9OC0piFNK6n0LghsglNMe2MwJtA==} 1529 | engines: {node: '>=12'} 1530 | cpu: [x64] 1531 | os: [darwin] 1532 | requiresBuild: true 1533 | dev: true 1534 | optional: true 1535 | 1536 | /esbuild-darwin-arm64/0.15.11: 1537 | resolution: {integrity: sha512-OMzhxSbS0lwwrW40HHjRCeVIJTURdXFA8c3GU30MlHKuPCcvWNUIKVucVBtNpJySXmbkQMDJdJNrXzNDyvoqvQ==} 1538 | engines: {node: '>=12'} 1539 | cpu: [arm64] 1540 | os: [darwin] 1541 | requiresBuild: true 1542 | dev: true 1543 | optional: true 1544 | 1545 | /esbuild-freebsd-64/0.15.11: 1546 | resolution: {integrity: sha512-8dKP26r0/Qyez8nTCwpq60QbuYKOeBygdgOAWGCRalunyeqWRoSZj9TQjPDnTTI9joxd3QYw3UhVZTKxO9QdRg==} 1547 | engines: {node: '>=12'} 1548 | cpu: [x64] 1549 | os: [freebsd] 1550 | requiresBuild: true 1551 | dev: true 1552 | optional: true 1553 | 1554 | /esbuild-freebsd-arm64/0.15.11: 1555 | resolution: {integrity: sha512-aSGiODiukLGGnSg/O9+cGO2QxEacrdCtCawehkWYTt5VX1ni2b9KoxpHCT9h9Y6wGqNHmXFnB47RRJ8BIqZgmQ==} 1556 | engines: {node: '>=12'} 1557 | cpu: [arm64] 1558 | os: [freebsd] 1559 | requiresBuild: true 1560 | dev: true 1561 | optional: true 1562 | 1563 | /esbuild-linux-32/0.15.11: 1564 | resolution: {integrity: sha512-lsrAfdyJBGx+6aHIQmgqUonEzKYeBnyfJPkT6N2dOf1RoXYYV1BkWB6G02tjsrz1d5wZzaTc3cF+TKmuTo/ZwA==} 1565 | engines: {node: '>=12'} 1566 | cpu: [ia32] 1567 | os: [linux] 1568 | requiresBuild: true 1569 | dev: true 1570 | optional: true 1571 | 1572 | /esbuild-linux-64/0.15.11: 1573 | resolution: {integrity: sha512-Y2Rh+PcyVhQqXKBTacPCltINN3uIw2xC+dsvLANJ1SpK5NJUtxv8+rqWpjmBgaNWKQT1/uGpMmA9olALy9PLVA==} 1574 | engines: {node: '>=12'} 1575 | cpu: [x64] 1576 | os: [linux] 1577 | requiresBuild: true 1578 | dev: true 1579 | optional: true 1580 | 1581 | /esbuild-linux-arm/0.15.11: 1582 | resolution: {integrity: sha512-TJllTVk5aSyqPFvvcHTvf6Wu1ZKhWpJ/qNmZO8LL/XeB+LXCclm7HQHNEIz6MT7IX8PmlC1BZYrOiw2sXSB95A==} 1583 | engines: {node: '>=12'} 1584 | cpu: [arm] 1585 | os: [linux] 1586 | requiresBuild: true 1587 | dev: true 1588 | optional: true 1589 | 1590 | /esbuild-linux-arm64/0.15.11: 1591 | resolution: {integrity: sha512-uhcXiTwTmD4OpxJu3xC5TzAAw6Wzf9O1XGWL448EE9bqGjgV1j+oK3lIHAfsHnuIn8K4nDW8yjX0Sv5S++oRuw==} 1592 | engines: {node: '>=12'} 1593 | cpu: [arm64] 1594 | os: [linux] 1595 | requiresBuild: true 1596 | dev: true 1597 | optional: true 1598 | 1599 | /esbuild-linux-mips64le/0.15.11: 1600 | resolution: {integrity: sha512-WD61y/R1M4BLe4gxXRypoQ0Ci+Vjf714QYzcPNkiYv5I8K8WDz2ZR8Bm6cqKxd6rD+e/rZgPDbhQ9PCf7TMHmA==} 1601 | engines: {node: '>=12'} 1602 | cpu: [mips64el] 1603 | os: [linux] 1604 | requiresBuild: true 1605 | dev: true 1606 | optional: true 1607 | 1608 | /esbuild-linux-ppc64le/0.15.11: 1609 | resolution: {integrity: sha512-JVleZS9oPVLTlBhPTWgOwxFWU/wMUdlBwTbGA4GF8c38sLbS13cupj+C8bLq929jU7EMWry4SaL+tKGIaTlqKg==} 1610 | engines: {node: '>=12'} 1611 | cpu: [ppc64] 1612 | os: [linux] 1613 | requiresBuild: true 1614 | dev: true 1615 | optional: true 1616 | 1617 | /esbuild-linux-riscv64/0.15.11: 1618 | resolution: {integrity: sha512-9aLIalZ2HFHIOZpmVU11sEAS9F8TnHw49daEjcgMpBXHFF57VuT9f9/9LKJhw781Gda0P9jDkuCWJ0tFbErvJw==} 1619 | engines: {node: '>=12'} 1620 | cpu: [riscv64] 1621 | os: [linux] 1622 | requiresBuild: true 1623 | dev: true 1624 | optional: true 1625 | 1626 | /esbuild-linux-s390x/0.15.11: 1627 | resolution: {integrity: sha512-sZHtiXXOKsLI3XGBGoYO4qKBzJlb8xNsWmvFiwFMHFzA4AXgDP1KDp7Dawe9C2pavTRBDvl+Ok4n/DHQ59oaTg==} 1628 | engines: {node: '>=12'} 1629 | cpu: [s390x] 1630 | os: [linux] 1631 | requiresBuild: true 1632 | dev: true 1633 | optional: true 1634 | 1635 | /esbuild-netbsd-64/0.15.11: 1636 | resolution: {integrity: sha512-hUC9yN06K9sg7ju4Vgu9ChAPdsEgtcrcLfyNT5IKwKyfpLvKUwCMZSdF+gRD3WpyZelgTQfJ+pDx5XFbXTlB0A==} 1637 | engines: {node: '>=12'} 1638 | cpu: [x64] 1639 | os: [netbsd] 1640 | requiresBuild: true 1641 | dev: true 1642 | optional: true 1643 | 1644 | /esbuild-openbsd-64/0.15.11: 1645 | resolution: {integrity: sha512-0bBo9SQR4t66Wd91LGMAqmWorzO0TTzVjYiifwoFtel8luFeXuPThQnEm5ztN4g0fnvcp7AnUPPzS/Depf17wQ==} 1646 | engines: {node: '>=12'} 1647 | cpu: [x64] 1648 | os: [openbsd] 1649 | requiresBuild: true 1650 | dev: true 1651 | optional: true 1652 | 1653 | /esbuild-sunos-64/0.15.11: 1654 | resolution: {integrity: sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==} 1655 | engines: {node: '>=12'} 1656 | cpu: [x64] 1657 | os: [sunos] 1658 | requiresBuild: true 1659 | dev: true 1660 | optional: true 1661 | 1662 | /esbuild-windows-32/0.15.11: 1663 | resolution: {integrity: sha512-O0/Wo1Wk6dc0rZSxkvGpmTNIycEznHmkObTFz2VHBhjPsO4ZpCgfGxNkCpz4AdAIeMczpTXt/8d5vdJNKEGC+Q==} 1664 | engines: {node: '>=12'} 1665 | cpu: [ia32] 1666 | os: [win32] 1667 | requiresBuild: true 1668 | dev: true 1669 | optional: true 1670 | 1671 | /esbuild-windows-64/0.15.11: 1672 | resolution: {integrity: sha512-x977Q4HhNjnHx00b4XLAnTtj5vfbdEvkxaQwC1Zh5AN8g5EX+izgZ6e5QgqJgpzyRNJqh4hkgIJF1pyy1be0mQ==} 1673 | engines: {node: '>=12'} 1674 | cpu: [x64] 1675 | os: [win32] 1676 | requiresBuild: true 1677 | dev: true 1678 | optional: true 1679 | 1680 | /esbuild-windows-arm64/0.15.11: 1681 | resolution: {integrity: sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==} 1682 | engines: {node: '>=12'} 1683 | cpu: [arm64] 1684 | os: [win32] 1685 | requiresBuild: true 1686 | dev: true 1687 | optional: true 1688 | 1689 | /esbuild/0.15.11: 1690 | resolution: {integrity: sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==} 1691 | engines: {node: '>=12'} 1692 | hasBin: true 1693 | requiresBuild: true 1694 | optionalDependencies: 1695 | '@esbuild/android-arm': 0.15.11 1696 | '@esbuild/linux-loong64': 0.15.11 1697 | esbuild-android-64: 0.15.11 1698 | esbuild-android-arm64: 0.15.11 1699 | esbuild-darwin-64: 0.15.11 1700 | esbuild-darwin-arm64: 0.15.11 1701 | esbuild-freebsd-64: 0.15.11 1702 | esbuild-freebsd-arm64: 0.15.11 1703 | esbuild-linux-32: 0.15.11 1704 | esbuild-linux-64: 0.15.11 1705 | esbuild-linux-arm: 0.15.11 1706 | esbuild-linux-arm64: 0.15.11 1707 | esbuild-linux-mips64le: 0.15.11 1708 | esbuild-linux-ppc64le: 0.15.11 1709 | esbuild-linux-riscv64: 0.15.11 1710 | esbuild-linux-s390x: 0.15.11 1711 | esbuild-netbsd-64: 0.15.11 1712 | esbuild-openbsd-64: 0.15.11 1713 | esbuild-sunos-64: 0.15.11 1714 | esbuild-windows-32: 0.15.11 1715 | esbuild-windows-64: 0.15.11 1716 | esbuild-windows-arm64: 0.15.11 1717 | dev: true 1718 | 1719 | /escalade/3.1.1: 1720 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 1721 | engines: {node: '>=6'} 1722 | dev: true 1723 | 1724 | /escape-string-regexp/1.0.5: 1725 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 1726 | engines: {node: '>=0.8.0'} 1727 | dev: true 1728 | 1729 | /estree-walker/1.0.1: 1730 | resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} 1731 | dev: true 1732 | 1733 | /esutils/2.0.3: 1734 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 1735 | engines: {node: '>=0.10.0'} 1736 | dev: true 1737 | 1738 | /fsevents/2.3.2: 1739 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 1740 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1741 | os: [darwin] 1742 | requiresBuild: true 1743 | dev: true 1744 | optional: true 1745 | 1746 | /function-bind/1.1.1: 1747 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 1748 | dev: true 1749 | 1750 | /gensync/1.0.0-beta.2: 1751 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1752 | engines: {node: '>=6.9.0'} 1753 | dev: true 1754 | 1755 | /get-func-name/2.0.0: 1756 | resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} 1757 | dev: true 1758 | 1759 | /get-intrinsic/1.1.3: 1760 | resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} 1761 | dependencies: 1762 | function-bind: 1.1.1 1763 | has: 1.0.3 1764 | has-symbols: 1.0.3 1765 | dev: true 1766 | 1767 | /globals/11.12.0: 1768 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 1769 | engines: {node: '>=4'} 1770 | dev: true 1771 | 1772 | /has-flag/3.0.0: 1773 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 1774 | engines: {node: '>=4'} 1775 | dev: true 1776 | 1777 | /has-property-descriptors/1.0.0: 1778 | resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} 1779 | dependencies: 1780 | get-intrinsic: 1.1.3 1781 | dev: true 1782 | 1783 | /has-symbols/1.0.3: 1784 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 1785 | engines: {node: '>= 0.4'} 1786 | dev: true 1787 | 1788 | /has/1.0.3: 1789 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 1790 | engines: {node: '>= 0.4.0'} 1791 | dependencies: 1792 | function-bind: 1.1.1 1793 | dev: true 1794 | 1795 | /is-core-module/2.10.0: 1796 | resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} 1797 | dependencies: 1798 | has: 1.0.3 1799 | dev: true 1800 | 1801 | /js-tokens/4.0.0: 1802 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1803 | dev: true 1804 | 1805 | /jsesc/0.5.0: 1806 | resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} 1807 | hasBin: true 1808 | dev: true 1809 | 1810 | /jsesc/2.5.2: 1811 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} 1812 | engines: {node: '>=4'} 1813 | hasBin: true 1814 | dev: true 1815 | 1816 | /json5/2.2.1: 1817 | resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} 1818 | engines: {node: '>=6'} 1819 | hasBin: true 1820 | dev: true 1821 | 1822 | /local-pkg/0.4.2: 1823 | resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} 1824 | engines: {node: '>=14'} 1825 | dev: true 1826 | 1827 | /lodash.debounce/4.0.8: 1828 | resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} 1829 | dev: true 1830 | 1831 | /loupe/2.3.4: 1832 | resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==} 1833 | dependencies: 1834 | get-func-name: 2.0.0 1835 | dev: true 1836 | 1837 | /ms/2.1.2: 1838 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1839 | dev: true 1840 | 1841 | /nanoid/3.3.4: 1842 | resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} 1843 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1844 | hasBin: true 1845 | dev: true 1846 | 1847 | /node-releases/2.0.6: 1848 | resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} 1849 | dev: true 1850 | 1851 | /object-keys/1.1.1: 1852 | resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 1853 | engines: {node: '>= 0.4'} 1854 | dev: true 1855 | 1856 | /object.assign/4.1.4: 1857 | resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} 1858 | engines: {node: '>= 0.4'} 1859 | dependencies: 1860 | call-bind: 1.0.2 1861 | define-properties: 1.1.4 1862 | has-symbols: 1.0.3 1863 | object-keys: 1.1.1 1864 | dev: true 1865 | 1866 | /path-parse/1.0.7: 1867 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1868 | dev: true 1869 | 1870 | /pathval/1.1.1: 1871 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} 1872 | dev: true 1873 | 1874 | /picocolors/1.0.0: 1875 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1876 | dev: true 1877 | 1878 | /picomatch/2.3.1: 1879 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1880 | engines: {node: '>=8.6'} 1881 | dev: true 1882 | 1883 | /postcss/8.4.18: 1884 | resolution: {integrity: sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==} 1885 | engines: {node: ^10 || ^12 || >=14} 1886 | dependencies: 1887 | nanoid: 3.3.4 1888 | picocolors: 1.0.0 1889 | source-map-js: 1.0.2 1890 | dev: true 1891 | 1892 | /regenerate-unicode-properties/10.1.0: 1893 | resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} 1894 | engines: {node: '>=4'} 1895 | dependencies: 1896 | regenerate: 1.4.2 1897 | dev: true 1898 | 1899 | /regenerate/1.4.2: 1900 | resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} 1901 | dev: true 1902 | 1903 | /regenerator-runtime/0.13.10: 1904 | resolution: {integrity: sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==} 1905 | dev: true 1906 | 1907 | /regenerator-transform/0.15.0: 1908 | resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} 1909 | dependencies: 1910 | '@babel/runtime': 7.19.4 1911 | dev: true 1912 | 1913 | /regexpu-core/5.2.1: 1914 | resolution: {integrity: sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==} 1915 | engines: {node: '>=4'} 1916 | dependencies: 1917 | regenerate: 1.4.2 1918 | regenerate-unicode-properties: 10.1.0 1919 | regjsgen: 0.7.1 1920 | regjsparser: 0.9.1 1921 | unicode-match-property-ecmascript: 2.0.0 1922 | unicode-match-property-value-ecmascript: 2.0.0 1923 | dev: true 1924 | 1925 | /regjsgen/0.7.1: 1926 | resolution: {integrity: sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==} 1927 | dev: true 1928 | 1929 | /regjsparser/0.9.1: 1930 | resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} 1931 | hasBin: true 1932 | dependencies: 1933 | jsesc: 0.5.0 1934 | dev: true 1935 | 1936 | /resolve/1.22.1: 1937 | resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} 1938 | hasBin: true 1939 | dependencies: 1940 | is-core-module: 2.10.0 1941 | path-parse: 1.0.7 1942 | supports-preserve-symlinks-flag: 1.0.0 1943 | dev: true 1944 | 1945 | /rollup/2.78.1: 1946 | resolution: {integrity: sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==} 1947 | engines: {node: '>=10.0.0'} 1948 | hasBin: true 1949 | optionalDependencies: 1950 | fsevents: 2.3.2 1951 | dev: true 1952 | 1953 | /rollup/2.79.1: 1954 | resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} 1955 | engines: {node: '>=10.0.0'} 1956 | hasBin: true 1957 | optionalDependencies: 1958 | fsevents: 2.3.2 1959 | dev: true 1960 | 1961 | /semver/6.3.0: 1962 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 1963 | hasBin: true 1964 | dev: true 1965 | 1966 | /source-map-js/1.0.2: 1967 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 1968 | engines: {node: '>=0.10.0'} 1969 | dev: true 1970 | 1971 | /strip-literal/0.4.2: 1972 | resolution: {integrity: sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==} 1973 | dependencies: 1974 | acorn: 8.8.0 1975 | dev: true 1976 | 1977 | /supports-color/5.5.0: 1978 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 1979 | engines: {node: '>=4'} 1980 | dependencies: 1981 | has-flag: 3.0.0 1982 | dev: true 1983 | 1984 | /supports-preserve-symlinks-flag/1.0.0: 1985 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1986 | engines: {node: '>= 0.4'} 1987 | dev: true 1988 | 1989 | /tinybench/2.3.0: 1990 | resolution: {integrity: sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==} 1991 | dev: true 1992 | 1993 | /tinypool/0.3.0: 1994 | resolution: {integrity: sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==} 1995 | engines: {node: '>=14.0.0'} 1996 | dev: true 1997 | 1998 | /tinyspy/1.0.2: 1999 | resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==} 2000 | engines: {node: '>=14.0.0'} 2001 | dev: true 2002 | 2003 | /to-fast-properties/2.0.0: 2004 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 2005 | engines: {node: '>=4'} 2006 | dev: true 2007 | 2008 | /tslib/2.4.0: 2009 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} 2010 | dev: true 2011 | 2012 | /type-detect/4.0.8: 2013 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} 2014 | engines: {node: '>=4'} 2015 | dev: true 2016 | 2017 | /typescript/4.8.4: 2018 | resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} 2019 | engines: {node: '>=4.2.0'} 2020 | hasBin: true 2021 | dev: true 2022 | 2023 | /unicode-canonical-property-names-ecmascript/2.0.0: 2024 | resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} 2025 | engines: {node: '>=4'} 2026 | dev: true 2027 | 2028 | /unicode-match-property-ecmascript/2.0.0: 2029 | resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} 2030 | engines: {node: '>=4'} 2031 | dependencies: 2032 | unicode-canonical-property-names-ecmascript: 2.0.0 2033 | unicode-property-aliases-ecmascript: 2.1.0 2034 | dev: true 2035 | 2036 | /unicode-match-property-value-ecmascript/2.0.0: 2037 | resolution: {integrity: sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==} 2038 | engines: {node: '>=4'} 2039 | dev: true 2040 | 2041 | /unicode-property-aliases-ecmascript/2.1.0: 2042 | resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} 2043 | engines: {node: '>=4'} 2044 | dev: true 2045 | 2046 | /update-browserslist-db/1.0.10_browserslist@4.21.4: 2047 | resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} 2048 | hasBin: true 2049 | peerDependencies: 2050 | browserslist: '>= 4.21.0' 2051 | dependencies: 2052 | browserslist: 4.21.4 2053 | escalade: 3.1.1 2054 | picocolors: 1.0.0 2055 | dev: true 2056 | 2057 | /vite/3.1.8: 2058 | resolution: {integrity: sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==} 2059 | engines: {node: ^14.18.0 || >=16.0.0} 2060 | hasBin: true 2061 | peerDependencies: 2062 | less: '*' 2063 | sass: '*' 2064 | stylus: '*' 2065 | terser: ^5.4.0 2066 | peerDependenciesMeta: 2067 | less: 2068 | optional: true 2069 | sass: 2070 | optional: true 2071 | stylus: 2072 | optional: true 2073 | terser: 2074 | optional: true 2075 | dependencies: 2076 | esbuild: 0.15.11 2077 | postcss: 8.4.18 2078 | resolve: 1.22.1 2079 | rollup: 2.78.1 2080 | optionalDependencies: 2081 | fsevents: 2.3.2 2082 | dev: true 2083 | 2084 | /vitest/0.24.3: 2085 | resolution: {integrity: sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==} 2086 | engines: {node: '>=v14.16.0'} 2087 | hasBin: true 2088 | peerDependencies: 2089 | '@edge-runtime/vm': '*' 2090 | '@vitest/browser': '*' 2091 | '@vitest/ui': '*' 2092 | happy-dom: '*' 2093 | jsdom: '*' 2094 | peerDependenciesMeta: 2095 | '@edge-runtime/vm': 2096 | optional: true 2097 | '@vitest/browser': 2098 | optional: true 2099 | '@vitest/ui': 2100 | optional: true 2101 | happy-dom: 2102 | optional: true 2103 | jsdom: 2104 | optional: true 2105 | dependencies: 2106 | '@types/chai': 4.3.3 2107 | '@types/chai-subset': 1.3.3 2108 | '@types/node': 18.11.0 2109 | chai: 4.3.6 2110 | debug: 4.3.4 2111 | local-pkg: 0.4.2 2112 | strip-literal: 0.4.2 2113 | tinybench: 2.3.0 2114 | tinypool: 0.3.0 2115 | tinyspy: 1.0.2 2116 | vite: 3.1.8 2117 | transitivePeerDependencies: 2118 | - less 2119 | - sass 2120 | - stylus 2121 | - supports-color 2122 | - terser 2123 | dev: true 2124 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from '@rollup/plugin-typescript' 2 | 3 | export default { 4 | input: "./packages/vue/src/index.ts", 5 | output: [ 6 | { 7 | format: "cjs", 8 | file: "packages/vue/dist/vue-next.cjs.js" 9 | }, 10 | { 11 | format: "es", 12 | file: "packages/vue/dist/vue-next.esm.js" 13 | } 14 | ], 15 | plugins: [typescript()] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2016", 4 | "lib": [ 5 | "DOM", 6 | "es6", 7 | "es2016" 8 | ], 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "types": [ 12 | "jest" 13 | ], 14 | "esModuleInterop": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "strict": true, 17 | "noImplicitAny": false, 18 | "skipLibCheck": true, 19 | "paths": { 20 | "@micro-vue-next/*": [ 21 | "./packages/*/src" 22 | ] 23 | } 24 | }, 25 | "include": [ 26 | "packages/*/src", 27 | "packages/*/__test__" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vitest/config' 2 | import * as path from "path"; 3 | 4 | export default defineConfig({ 5 | test: { 6 | globals: true 7 | }, 8 | resolve: { 9 | alias: [ 10 | { 11 | find: /@micro-vue-next\/(\w*)/, 12 | replacement: path.resolve(__dirname, "packages") + "/$1/src" 13 | } 14 | ] 15 | } 16 | }) 17 | --------------------------------------------------------------------------------