- run: pnpm run size
- - name: Upload Size Data
- uses: actions/upload-artifact@v4
- with:
- name: size-data
- path: temp/size
-
+ - name: Download Previous Size Data
+ uses: dawidd6/action-download-artifact@v2
+ if: ${{ github.event_name == 'push' }}
+ with:
+ branch: main
+ workflow: size-data.yml
+ event: push
+ name: size-data
+ path: temp/size-prev
+ if_no_artifact_found: warn
+
- name: Save PR number & base branch
if: ${{github.event_name == 'pull_request'}}
run: |
// Private package, browser only + no syntax restrictions
{
files: [
- 'packages/template-explorer/**',
- 'packages/sfc-playground/**',
+ 'packages-private/template-explorer/**',
+ 'packages-private/sfc-playground/**',
+ 'playground/**',
],
rules: {
'no-restricted-globals': ['error', ...NodeGlobals],
{
"private": true,
- "version": "3.5.0-beta.1",
- "packageManager": "pnpm@9.6.0",
+ "version": "3.5.6",
+ "packageManager": "pnpm@9.10.0",
"type": "module",
"scripts": {
- "dev": "node scripts/dev.js",
+ "dev": "node scripts/dev.js vue vue-vapor",
"build": "node scripts/build.js",
- "build-dts": "tsc -p tsconfig.build-browser.json && tsc -p tsconfig.build-node.json && rollup -c rollup.dts.config.js",
- "clean": "rimraf packages/*/dist temp .eslintcache",
- "size": "run-s \"size-*\" && tsx scripts/usage-size.ts",
+ "build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js",
+ "clean": "rimraf --glob packages/*/dist temp .eslintcache",
+ "size": "run-s \"size-*\" && node scripts/usage-size.js",
- "size-global": "node scripts/build.js vue runtime-dom -f global -p --size",
- "size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
- "size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
+ "size-global": "node scripts/build.js vue vue-vapor runtime-dom runtime-vapor compiler-dom compiler-vapor -f global -p --size",
+ "size-esm-runtime": "node scripts/build.js vue vue-vapor -f esm-bundler-runtime",
+ "size-esm": "node scripts/build.js runtime-shared runtime-dom runtime-vapor runtime-core reactivity shared -f esm-bundler",
"check": "tsc --incremental --noEmit",
"lint": "eslint --cache .",
"format": "prettier --write --cache .",
"format-check": "prettier --check --cache .",
"test": "vitest",
- "test-unit": "vitest -c vitest.unit.config.ts",
- "test-e2e": "node scripts/build.js vue vue-vapor -f global -d && vitest -c vitest.e2e.config.ts",
+ "test-unit": "vitest --project unit",
- "test-e2e": "node scripts/build.js vue -f global -d && vitest --project e2e",
++ "test-e2e": "node scripts/build.js vue vue-vapor -f global -d && vitest --project e2e",
"test-dts": "run-s build-dts test-dts-only",
- "test-dts-only": "tsc -p packages/dts-built-test/tsconfig.json && tsc -p ./packages/dts-test/tsconfig.test.json",
- "test-coverage": "vitest -c vitest.unit.config.ts --coverage",
+ "test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json",
+ "test-coverage": "vitest run --project unit --coverage",
"test-bench": "vitest bench",
"release": "node scripts/release.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"dev-esm": "node scripts/dev.js -if esm-bundler-runtime",
+ "dev-prepare-cjs": "node scripts/prepare-cjs.js || npm run build-all-cjs",
"dev-compiler": "run-p \"dev template-explorer\" serve",
- "dev-sfc": "run-s dev-sfc-prepare dev-sfc-run",
- "dev-sfc-prepare": "node scripts/pre-dev-sfc.js || npm run build-all-cjs",
+ "dev-sfc": "run-s dev-prepare-cjs dev-sfc-run",
- "dev-sfc-serve": "vite packages/sfc-playground --host",
+ "dev-sfc-serve": "vite packages-private/sfc-playground --host",
"dev-sfc-run": "run-p \"dev compiler-sfc -f esm-browser\" \"dev vue -if esm-bundler-runtime\" \"dev vue -ipf esm-browser-runtime\" \"dev server-renderer -if esm-bundler\" dev-sfc-serve",
+ "dev-vapor": "pnpm -C playground run dev",
"serve": "serve",
- "open": "open http://localhost:3000/packages/template-explorer/local.html",
+ "open": "open http://localhost:3000/packages-private/template-explorer/local.html",
"build-sfc-playground": "run-s build-all-cjs build-runtime-esm build-browser-esm build-ssr-esm build-sfc-playground-self",
"build-all-cjs": "node scripts/build.js vue runtime compiler reactivity shared -af cjs",
"build-runtime-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js vue -f esm-browser-runtime",
"build-browser-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler && node scripts/build.js vue -f esm-browser",
- "build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer -f esm-browser",
+ "build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer vue-vapor -f esm-browser",
- "build-sfc-playground-self": "cd packages/sfc-playground && npm run build",
+ "build-sfc-playground-self": "cd packages-private/sfc-playground && npm run build",
"preinstall": "npx only-allow pnpm",
"postinstall": "simple-git-hooks"
},
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "5.0.4",
- "@swc/core": "^1.7.6",
+ "@swc/core": "^1.7.26",
"@types/hash-sum": "^1.0.2",
- "@types/node": "^20.14.14",
+ "@types/node": "^20.16.5",
"@types/semver": "^7.5.8",
"@types/serve-handler": "^6.1.4",
- "@vitest/coverage-istanbul": "^1.6.0",
- "@vitest/ui": "^1.6.0",
+ "@vitest/coverage-v8": "^2.1.1",
++ "@vitest/ui": "^2.1.1",
"@vue/consolidate": "1.0.0",
"conventional-changelog-cli": "^5.0.0",
"enquirer": "^2.4.1",
setVH()
const useSSRMode = ref(false)
+const useVaporMode = ref(true)
-const { productionMode, vueVersion, importMap } = useVueImportMap({
+ const AUTO_SAVE_STORAGE_KEY = 'vue-sfc-playground-auto-save'
+ const initAutoSave: boolean = JSON.parse(
+ localStorage.getItem(AUTO_SAVE_STORAGE_KEY) ?? 'true',
+ )
+ const autoSave = ref(initAutoSave)
+
+const {
+ vueVersion,
+ productionMode,
+ importMap: vueImportMap,
+} = useVueImportMap({
runtimeDev: import.meta.env.PROD
? `${location.origin}/vue.runtime.esm-browser.js`
: `${location.origin}/src/vue-dev-proxy`,
useSSRMode.value = !useSSRMode.value
}
+function toggleVapor() {
+ useVaporMode.value = !useVaporMode.value
+}
+
+ function toggleAutoSave() {
+ autoSave.value = !autoSave.value
+ localStorage.setItem(AUTO_SAVE_STORAGE_KEY, String(autoSave.value))
+ }
+
function reloadPage() {
replRef.value?.reload()
}
:store="store"
:prod="productionMode"
:ssr="useSSRMode"
+ :vapor="useVaporMode"
+ :autoSave="autoSave"
@toggle-theme="toggleTheme"
@toggle-prod="toggleProdMode"
@toggle-ssr="toggleSSR"
+ @toggle-autosave="toggleAutoSave"
+ @toggle-vapor="toggleVapor"
@reload-page="reloadPage"
/>
<Repl
store: ReplStore
prod: boolean
ssr: boolean
+ vapor: boolean
+ autoSave: boolean
}>()
const emit = defineEmits([
'toggle-theme',
'toggle-ssr',
'toggle-prod',
+ 'toggle-vapor',
+ 'toggle-autosave',
'reload-page',
])
}
.toggle-prod span,
- .toggle-ssr span {
+.toggle-vapor span,
+ .toggle-ssr span,
+ .toggle-autosave span {
font-size: 12px;
border-radius: 4px;
padding: 4px 6px;
})
}
- copyFile(`../vue/dist/vue.esm-browser.js`)
- copyFile(`../vue/dist/vue.esm-browser.prod.js`)
- copyFile(`../vue/dist/vue.runtime.esm-browser.js`)
- copyFile(`../vue/dist/vue.runtime.esm-browser.prod.js`)
- copyFile(`../server-renderer/dist/server-renderer.esm-browser.js`)
- copyFile(`../vue-vapor/dist/vue-vapor.esm-browser.js`)
+ copyFile(`vue/dist/vue.esm-browser.js`)
+ copyFile(`vue/dist/vue.esm-browser.prod.js`)
+ copyFile(`vue/dist/vue.runtime.esm-browser.js`)
+ copyFile(`vue/dist/vue.runtime.esm-browser.prod.js`)
+ copyFile(`server-renderer/dist/server-renderer.esm-browser.js`)
++ copyFile(`vue-vapor/dist/vue-vapor.esm-browser.js`)
},
}
}
"enableNonBrowserBranches": true
},
"dependencies": {
- "monaco-editor": "^0.50.0",
- "source-map-js": "^1.2.0"
+ "@vue/compiler-vapor": "workspace:^",
+ "monaco-editor": "^0.51.0",
+ "source-map-js": "^1.2.1"
}
}
import { IS_REF, UNREF } from '../runtimeHelpers'
import { BindingTypes } from '../options'
-const isLiteralWhitelisted = /*@__PURE__*/ makeMap('true,false,null,this')
+export const isLiteralWhitelisted: (key: string) => boolean =
- /*#__PURE__*/ makeMap('true,false,null,this')
++ /*@__PURE__*/ makeMap('true,false,null,this')
export const transformExpression: NodeTransform = (node, context) => {
if (node.type === NodeTypes.INTERPOLATION) {
}
export const isMemberExpressionNode: (
- path: string,
+ exp: ExpressionNode,
- context: TransformContext,
+ context: Pick<TransformContext, 'expressionPlugins'>,
) => boolean = __BROWSER__
? (NOOP as any)
- : (path, context) => {
+ : (exp, context) => {
try {
- let ret: Expression = parseExpression(path, {
- plugins: context.expressionPlugins,
- })
+ let ret: Node =
+ exp.ast ||
+ parseExpression(getExpSource(exp), {
+ plugins: context.expressionPlugins
+ ? [...context.expressionPlugins, 'typescript']
+ : ['typescript'],
+ })
ret = unwrapTSNode(ret) as Expression
return (
ret.type === 'MemberExpression' ||
}
export const isMemberExpression: (
- path: string,
+ exp: ExpressionNode,
- context: TransformContext,
+ context: Pick<TransformContext, 'expressionPlugins'>,
) => boolean = __BROWSER__ ? isMemberExpressionBrowser : isMemberExpressionNode
- context: TransformContext,
+ const fnExpRE =
+ /^\s*(async\s*)?(\([^)]*?\)|[\w$_]+)\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/
+
+ export const isFnExpressionBrowser: (exp: ExpressionNode) => boolean = exp =>
+ fnExpRE.test(getExpSource(exp))
+
+ export const isFnExpressionNode: (
+ exp: ExpressionNode,
- context: TransformContext,
++ context: Pick<TransformContext, 'expressionPlugins'>,
+ ) => boolean = __BROWSER__
+ ? (NOOP as any)
+ : (exp, context) => {
+ try {
+ let ret: Node =
+ exp.ast ||
+ parseExpression(getExpSource(exp), {
+ plugins: context.expressionPlugins
+ ? [...context.expressionPlugins, 'typescript']
+ : ['typescript'],
+ })
+ // parser may parse the exp as statements when it contains semicolons
+ if (ret.type === 'Program') {
+ ret = ret.body[0]
+ if (ret.type === 'ExpressionStatement') {
+ ret = ret.expression
+ }
+ }
+ ret = unwrapTSNode(ret) as Expression
+ return (
+ ret.type === 'FunctionExpression' ||
+ ret.type === 'ArrowFunctionExpression'
+ )
+ } catch (e) {
+ return false
+ }
+ }
+
+ export const isFnExpression: (
+ exp: ExpressionNode,
++ context: Pick<TransformContext, 'expressionPlugins'>,
+ ) => boolean = __BROWSER__ ? isFnExpressionBrowser : isFnExpressionNode
+
export function advancePositionWithClone(
pos: Position,
source: string,
isStaticExp,
} from '@vue/compiler-core'
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../runtimeHelpers'
-import { capitalize, makeMap } from '@vue/shared'
+import { capitalize, isString, makeMap } from '@vue/shared'
- const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
- const isNonKeyModifier = /*#__PURE__*/ makeMap(
+ const isEventOptionModifier = /*@__PURE__*/ makeMap(`passive,once,capture`)
+ const isNonKeyModifier = /*@__PURE__*/ makeMap(
// event propagation management
`stop,prevent,self,` +
// system modifiers + exact
`middle`,
)
// left & right could be mouse or key modifiers based on event type
- const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right')
- const isKeyboardEvent = /*#__PURE__*/ makeMap(
- `onkeyup,onkeydown,onkeypress`,
- true,
- )
+ const maybeKeyModifier = /*@__PURE__*/ makeMap('left,right')
+ const isKeyboardEvent = /*@__PURE__*/ makeMap(`onkeyup,onkeydown,onkeypress`)
-const resolveModifiers = (
- key: ExpressionNode,
+export const resolveModifiers = (
+ key: ExpressionNode | string,
- modifiers: string[],
+ modifiers: SimpleExpressionNode[],
- context: TransformContext,
+ context: TransformContext | null,
loc: SourceLocation,
-) => {
+): {
+ keyModifiers: string[]
+ nonKeyModifiers: string[]
+ eventOptionModifiers: string[]
+} => {
const keyModifiers = []
const nonKeyModifiers = []
const eventOptionModifiers = []
// e.g. .passive & .capture
eventOptionModifiers.push(modifier)
} else {
+ const keyString = isString(key)
+ ? key
+ : isStaticExp(key)
+ ? key.content
+ : null
+
// runtimeModifiers: modifiers that needs runtime guards
if (maybeKeyModifier(modifier)) {
- if (isStaticExp(key)) {
- if (
- isKeyboardEvent((key as SimpleExpressionNode).content.toLowerCase())
- ) {
+ if (keyString) {
- if (isKeyboardEvent(keyString)) {
++ if (isKeyboardEvent(keyString.toLowerCase())) {
keyModifiers.push(modifier)
} else {
nonKeyModifiers.push(modifier)
(definedOptions ? `\n ...${definedOptions},` : '')
ctx.s.prependLeft(
startOffset,
- `\n${genDefaultAs} /*#__PURE__*/${ctx.helper(
+ `\n${genDefaultAs} /*@__PURE__*/${ctx.helper(
`defineComponent`,
+ vapor,
)}({${def}${runtimeOptions}\n ${
hasAwait ? `async ` : ``
}setup(${args}) {\n${exposeCall}`,
--- /dev/null
- const parser = new DOMParser()
+/**
+ * @vitest-environment jsdom
+ */
+
- function parseHTML(html: string) {
++const parser: DOMParser = new DOMParser()
+
- function checkAbbr(template: string, abbrevation: string, expected: string) {
++function parseHTML(html: string): string {
+ return parser.parseFromString(html, 'text/html').body.innerHTML
+}
+
++function checkAbbr(
++ template: string,
++ abbrevation: string,
++ expected: string,
++): void {
+ // TODO do some optimzations to make sure template === abbrevation
+ expect(parseHTML(abbrevation)).toBe(expected)
+}
+
+test('template abbreviation', () => {
+ checkAbbr('<div>hello</div>', '<div>hello', '<div>hello</div>')
+ checkAbbr(
+ '<div><div>hello</div></div>',
+ '<div><div>hello',
+ '<div><div>hello</div></div>',
+ )
+ checkAbbr(
+ '<div><span>foo</span><span/></div>',
+ '<div><span>foo</span><span>',
+ '<div><span>foo</span><span></span></div>',
+ )
+ checkAbbr(
+ '<div><hr/><div/></div>',
+ '<div><hr><div>',
+ '<div><hr><div></div></div>',
+ )
+ checkAbbr(
+ '<div><div/><hr/></div>',
+ '<div><div></div><hr>',
+ '<div><div></div><hr></div>',
+ )
+
+ checkAbbr('<span/>hello', '<span></span>hello', '<span></span>hello')
+})
--- /dev/null
- _delegate(n0, "click", () => _ctx.a)
- _delegate(n0, "click", () => _ctx.b)
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`compiler: element transform > component > do not resolve component from non-script-setup bindings 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Example = _resolveComponent("Example")
+ const n0 = _createComponent(_component_Example, null, null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > generate multi root component 1`] = `
+"import { createComponent as _createComponent, template as _template } from 'vue/vapor';
+const t0 = _template("123")
+
+export function render(_ctx) {
+ const n1 = t0()
+ const n0 = _createComponent(_ctx.Comp)
+ return [n0, n1]
+}"
+`;
+
+exports[`compiler: element transform > component > generate single root component 1`] = `
+"import { createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const n0 = _createComponent(_ctx.Comp, null, null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > import + resolve component 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, null, null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > resolve component from setup bindings (inline const) 1`] = `
+"(() => {
+ const n0 = _createComponent(Example, null, null, true)
+ return n0
+})()"
+`;
+
+exports[`compiler: element transform > component > resolve component from setup bindings (inline) 1`] = `
+"(() => {
+ const n0 = _createComponent(_unref(Example), null, null, true)
+ return n0
+})()"
+`;
+
+exports[`compiler: element transform > component > resolve component from setup bindings 1`] = `
+"import { createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const n0 = _createComponent(_ctx.Example, null, null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > resolve namespaced component from props bindings (inline) 1`] = `
+"(() => {
+ const n0 = _createComponent(Foo.Example, null, null, true)
+ return n0
+})()"
+`;
+
+exports[`compiler: element transform > component > resolve namespaced component from props bindings (non-inline) 1`] = `
+"import { createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const n0 = _createComponent(_ctx.Foo.Example, null, null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > resolve namespaced component from setup bindings (inline const) 1`] = `
+"(() => {
+ const n0 = _createComponent(Foo.Example, null, null, true)
+ return n0
+})()"
+`;
+
+exports[`compiler: element transform > component > resolve namespaced component from setup bindings 1`] = `
+"import { createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const n0 = _createComponent(_ctx.Foo.Example, null, null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > should wrap as function if v-on expression is inline statement 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ { onBar: () => $event => (_ctx.handleBar($event)) }
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > static props 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ {
+ id: () => ("foo"),
+ class: () => ("bar")
+ }
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > v-bind="obj" 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ () => (_ctx.obj)
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > v-bind="obj" after static prop 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ { id: () => ("foo") },
+ () => (_ctx.obj)
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > v-bind="obj" before static prop 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ () => (_ctx.obj),
+ { id: () => ("foo") }
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > v-bind="obj" between static props 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ { id: () => ("foo") },
+ () => (_ctx.obj),
+ { class: () => ("bar") }
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component > v-on="obj" 1`] = `
+"import { resolveComponent as _resolveComponent, toHandlers as _toHandlers, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ () => (_toHandlers(_ctx.obj))
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component with dynamic event arguments 1`] = `
+"import { toHandlerKey as _toHandlerKey } from 'vue';
+import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ () => ({ [_toHandlerKey(_ctx.foo-_ctx.bar)]: () => _ctx.bar }),
+ () => ({ [_toHandlerKey(_ctx.baz)]: () => _ctx.qux })
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > component with dynamic prop arguments 1`] = `
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
+
+export function render(_ctx) {
+ const _component_Foo = _resolveComponent("Foo")
+ const n0 = _createComponent(_component_Foo, [
+ () => ({ [_ctx.foo-_ctx.bar]: _ctx.bar }),
+ () => ({ [_ctx.baz]: _ctx.qux })
+ ], null, true)
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > empty template 1`] = `
+"
+export function render(_ctx) {
+ return null
+}"
+`;
+
+exports[`compiler: element transform > invalid html nesting 1`] = `
+"import { insert as _insert, template as _template } from 'vue/vapor';
+const t0 = _template("<div>123</div>")
+const t1 = _template("<p></p>")
+const t2 = _template("<form></form>")
+
+export function render(_ctx) {
+ const n1 = t1()
+ const n0 = t0()
+ const n3 = t2()
+ const n2 = t2()
+ _insert(n0, n1)
+ _insert(n2, n3)
+ return [n1, n3]
+}"
+`;
+
+exports[`compiler: element transform > props + children 1`] = `
+"import { template as _template } from 'vue/vapor';
+const t0 = _template("<div id=\\"foo\\"><span></span></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > props merging: class 1`] = `
+"import { renderEffect as _renderEffect, setClass as _setClass, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setClass(n0, ["foo", { bar: _ctx.isBar }]))
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > props merging: event handlers 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
++ _delegate(n0, "click", () => _ctx.a, {
++ keys: ["foo"]
++ })
++ _delegate(n0, "click", () => _ctx.b, {
++ keys: ["bar"]
++ })
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > props merging: style 1`] = `
+"import { renderEffect as _renderEffect, setStyle as _setStyle, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setStyle(n0, ["color: green", { color: 'red' }]))
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > static props 1`] = `
+"import { template as _template } from 'vue/vapor';
+const t0 = _template("<div id=\\"foo\\" class=\\"bar\\"></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > v-bind="obj" 1`] = `
+"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setDynamicProps(n0, _ctx.obj))
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > v-bind="obj" after static prop 1`] = `
+"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setDynamicProps(n0, { id: "foo" }, _ctx.obj))
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > v-bind="obj" before static prop 1`] = `
+"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setDynamicProps(n0, _ctx.obj, { id: "foo" }))
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > v-bind="obj" between static props 1`] = `
+"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setDynamicProps(n0, { id: "foo" }, _ctx.obj, { class: "bar" }))
+ return n0
+}"
+`;
+
+exports[`compiler: element transform > v-on="obj" 1`] = `
+"import { renderEffect as _renderEffect, setDynamicEvents as _setDynamicEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => _setDynamicEvents(n0, _ctx.obj))
+ return n0
+}"
+`;
--- /dev/null
- modifiers: ["right"]
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`v-on > complex member expression w/ prefixIdentifiers: true 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => _ctx.a['b' + _ctx.c])
+ return n0
+}"
+`;
+
+exports[`v-on > dynamic arg 1`] = `
+"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => {
+ _on(n0, _ctx.event, () => _ctx.handler, {
+ effect: true
+ })
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > dynamic arg with complex exp prefixing 1`] = `
+"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => {
+ _on(n0, _ctx.event(_ctx.foo), () => _ctx.handler, {
+ effect: true
+ })
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > dynamic arg with prefixing 1`] = `
+"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => {
+ _on(n0, _ctx.event, () => _ctx.handler, {
+ effect: true
+ })
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > event modifier 1`] = `
+"import { delegate as _delegate, on as _on, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<a></a>")
+const t1 = _template("<form></form>")
+const t2 = _template("<div></div>")
+const t3 = _template("<input>")
+_delegateEvents("click", "contextmenu", "mouseup", "keyup")
+
+export function render(_ctx) {
+ const n0 = t0()
+ const n1 = t1()
+ const n2 = t0()
+ const n3 = t2()
+ const n4 = t2()
+ const n5 = t0()
+ const n6 = t2()
+ const n7 = t3()
+ const n8 = t3()
+ const n9 = t3()
+ const n10 = t3()
+ const n11 = t3()
+ const n12 = t3()
+ const n13 = t3()
+ const n14 = t3()
+ const n15 = t3()
+ const n16 = t3()
+ const n17 = t3()
+ const n18 = t3()
+ const n19 = t3()
+ const n20 = t3()
+ const n21 = t3()
+ _delegate(n0, "click", () => _ctx.handleEvent, {
+ modifiers: ["stop"]
+ })
+ _on(n1, "submit", () => _ctx.handleEvent, {
+ modifiers: ["prevent"]
+ })
+ _delegate(n2, "click", () => _ctx.handleEvent, {
+ modifiers: ["stop", "prevent"]
+ })
+ _delegate(n3, "click", () => _ctx.handleEvent, {
+ modifiers: ["self"]
+ })
+ _on(n4, "click", () => _ctx.handleEvent, {
+ capture: true
+ })
+ _on(n5, "click", () => _ctx.handleEvent, {
+ once: true
+ })
+ _on(n6, "scroll", () => _ctx.handleEvent, {
+ passive: true
+ })
+ _delegate(n7, "contextmenu", () => _ctx.handleEvent, {
+ modifiers: ["right"]
+ })
+ _delegate(n8, "click", () => _ctx.handleEvent, {
+ modifiers: ["left"]
+ })
+ _delegate(n9, "mouseup", () => _ctx.handleEvent, {
+ modifiers: ["middle"]
+ })
+ _delegate(n10, "contextmenu", () => _ctx.handleEvent, {
++ modifiers: ["right"],
++ keys: ["enter"]
+ })
+ _delegate(n11, "keyup", () => _ctx.handleEvent, {
+ keys: ["enter"]
+ })
+ _delegate(n12, "keyup", () => _ctx.handleEvent, {
+ keys: ["tab"]
+ })
+ _delegate(n13, "keyup", () => _ctx.handleEvent, {
+ keys: ["delete"]
+ })
+ _delegate(n14, "keyup", () => _ctx.handleEvent, {
+ keys: ["esc"]
+ })
+ _delegate(n15, "keyup", () => _ctx.handleEvent, {
+ keys: ["space"]
+ })
+ _delegate(n16, "keyup", () => _ctx.handleEvent, {
+ keys: ["up"]
+ })
+ _delegate(n17, "keyup", () => _ctx.handleEvent, {
+ keys: ["down"]
+ })
+ _delegate(n18, "keyup", () => _ctx.handleEvent, {
+ keys: ["left"]
+ })
+ _delegate(n19, "keyup", () => _ctx.submit, {
+ modifiers: ["middle"]
+ })
+ _delegate(n20, "keyup", () => _ctx.submit, {
+ modifiers: ["middle", "self"]
+ })
+ _delegate(n21, "keyup", () => _ctx.handleEvent, {
+ modifiers: ["self"],
+ keys: ["enter"]
+ })
+ return [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20, n21]
+}"
+`;
+
+exports[`v-on > function expression w/ prefixIdentifiers: true 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => e => _ctx.foo(e))
+ return n0
+}"
+`;
+
+exports[`v-on > inline statement w/ prefixIdentifiers: true 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => (_ctx.foo($event)))
+ return n0
+}"
+`;
+
+exports[`v-on > multiple inline statements w/ prefixIdentifiers: true 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => {_ctx.foo($event);_ctx.bar()})
+ return n0
+}"
+`;
+
+exports[`v-on > should NOT add a prefix to $event if the expression is a function expression 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => {_ctx.i++;_ctx.foo($event)})
+ return n0
+}"
+`;
+
+exports[`v-on > should NOT wrap as function if expression is already function expression (with Typescript) 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => (e: any): any => _ctx.foo(e))
+ return n0
+}"
+`;
+
+exports[`v-on > should NOT wrap as function if expression is already function expression (with newlines) 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () =>
+ $event => {
+ _ctx.foo($event)
+ }
+ )
+ return n0
+}"
+`;
+
+exports[`v-on > should NOT wrap as function if expression is already function expression 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => _ctx.foo($event))
+ return n0
+}"
+`;
+
+exports[`v-on > should NOT wrap as function if expression is complex member expression 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => _ctx.a['b' + _ctx.c])
+ return n0
+}"
+`;
+
+exports[`v-on > should delegate event 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => _ctx.test)
+ return n0
+}"
+`;
+
+exports[`v-on > should handle multi-line statement 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => {
+_ctx.foo();
+_ctx.bar()
+})
+ return n0
+}"
+`;
+
+exports[`v-on > should handle multiple inline statement 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => {_ctx.foo();_ctx.bar()})
+ return n0
+}"
+`;
+
+exports[`v-on > should not prefix member expression 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => _ctx.foo.bar)
+ return n0
+}"
+`;
+
+exports[`v-on > should not wrap keys guard if no key modifier is present 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("keyup")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "keyup", () => _ctx.test, {
+ modifiers: ["exact"]
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should support multiple events and modifiers options w/ prefixIdentifiers: true 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click", "keyup")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => _ctx.test, {
+ modifiers: ["stop"]
+ })
+ _delegate(n0, "keyup", () => _ctx.test, {
+ keys: ["enter"]
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should support multiple modifiers and event options w/ prefixIdentifiers: true 1`] = `
+"import { on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _on(n0, "click", () => _ctx.test, {
+ modifiers: ["stop", "prevent"],
+ capture: true,
+ once: true
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should transform click.middle 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("mouseup")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "mouseup", () => _ctx.test, {
+ modifiers: ["middle"]
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should transform click.middle 2`] = `
+"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => {
+ _on(n0, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _ctx.test, {
+ modifiers: ["middle"],
+ effect: true
+ })
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should transform click.right 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("contextmenu")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "contextmenu", () => _ctx.test, {
+ modifiers: ["right"]
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should transform click.right 2`] = `
+"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => {
+ _on(n0, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _ctx.test, {
+ modifiers: ["right"],
+ keys: ["right"],
+ effect: true
+ })
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should wrap as function if expression is inline statement 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => $event => (_ctx.i++))
+ return n0
+}"
+`;
+
+exports[`v-on > should wrap both for dynamic key event w/ left/right modifiers 1`] = `
+"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _renderEffect(() => {
+ _on(n0, _ctx.e, () => _ctx.test, {
+ modifiers: ["left"],
+ keys: ["left"],
+ effect: true
+ })
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should wrap in unref if identifier is setup-maybe-ref w/ inline: true 1`] = `
+"(() => {
+ const n0 = t0()
+ const n1 = t0()
+ const n2 = t0()
+ _delegate(n0, "click", () => $event => (x.value=_unref(y)))
+ _delegate(n1, "click", () => $event => (x.value++))
+ _delegate(n2, "click", () => $event => ({ x: x.value } = _unref(y)))
+ return [n0, n1, n2]
+})()"
+`;
+
+exports[`v-on > should wrap keys guard for keyboard events or dynamic events 1`] = `
+"import { on as _on, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _on(n0, "keydown", () => _ctx.test, {
+ modifiers: ["stop", "ctrl"],
+ keys: ["a"],
+ capture: true
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > should wrap keys guard for static key event w/ left/right modifiers 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("keyup")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "keyup", () => _ctx.test, {
+ keys: ["left"]
+ })
+ return n0
+}"
+`;
+
+exports[`v-on > simple expression 1`] = `
+"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
+const t0 = _template("<div></div>")
+_delegateEvents("click")
+
+export function render(_ctx) {
+ const n0 = t0()
+ _delegate(n0, "click", () => _ctx.handleClick)
+ return n0
+}"
+`;
--- /dev/null
- import { type CompilerOptions, generate, parse, transform } from '../../src'
++import type { RootNode } from '@vue/compiler-dom'
++import {
++ type CompilerOptions,
++ type RootIRNode,
++ generate,
++ parse,
++ transform,
++} from '../../src'
+
+export function makeCompile(options: CompilerOptions = {}) {
- return (template: string, overrideOptions: CompilerOptions = {}) => {
++ return (
++ template: string,
++ overrideOptions: CompilerOptions = {},
++ ): {
++ ast: RootNode
++ ir: RootIRNode
++ code: string
++ helpers: Set<string>
++ vaporHelpers: Set<string>
++ } => {
+ const ast = parse(template, {
+ prefixIdentifiers: true,
+ ...options,
+ ...overrideOptions,
+ })
+ const ir = transform(ast, {
+ prefixIdentifiers: true,
+ ...options,
+ ...overrideOptions,
+ })
+ const { code, helpers, vaporHelpers } = generate(ir, {
+ prefixIdentifiers: true,
+ ...options,
+ ...overrideOptions,
+ })
+ return { ast, ir, code, helpers, vaporHelpers }
+ }
+}
--- /dev/null
- expect(ir.template[0]).toMatchObject('<div></div>')
+import { ErrorCodes, NodeTypes } from '@vue/compiler-core'
+import {
+ IRNodeTypes,
+ transformChildren,
+ transformElement,
+ transformSlotOutlet,
+ transformText,
+ transformVBind,
+ transformVOn,
+ transformVShow,
+} from '../../src'
+import { makeCompile } from './_utils'
+
+const compileWithSlotsOutlet = makeCompile({
+ nodeTransforms: [
+ transformText,
+ transformSlotOutlet,
+ transformElement,
+ transformChildren,
+ ],
+ directiveTransforms: {
+ bind: transformVBind,
+ on: transformVOn,
+ show: transformVShow,
+ },
+})
+
+describe('compiler: transform <slot> outlets', () => {
+ test('default slot outlet', () => {
+ const { ir, code, vaporHelpers } = compileWithSlotsOutlet(`<slot />`)
+ expect(code).toMatchSnapshot()
+ expect(vaporHelpers).toContain('createSlot')
+ expect(ir.block.effect).toEqual([])
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: {
+ type: NodeTypes.SIMPLE_EXPRESSION,
+ content: 'default',
+ isStatic: true,
+ },
+ props: [],
+ fallback: undefined,
+ },
+ ])
+ })
+
+ test('statically named slot outlet', () => {
+ const { ir, code } = compileWithSlotsOutlet(`<slot name="foo" />`)
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: {
+ type: NodeTypes.SIMPLE_EXPRESSION,
+ content: 'foo',
+ isStatic: true,
+ },
+ },
+ ])
+ })
+
+ test('dynamically named slot outlet', () => {
+ const { ir, code } = compileWithSlotsOutlet(`<slot :name="foo + bar" />`)
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: {
+ type: NodeTypes.SIMPLE_EXPRESSION,
+ content: 'foo + bar',
+ isStatic: false,
+ },
+ },
+ ])
+ })
+
+ test('dynamically named slot outlet with v-bind shorthand', () => {
+ const { ir, code } = compileWithSlotsOutlet(`<slot :name />`)
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: {
+ type: NodeTypes.SIMPLE_EXPRESSION,
+ content: 'name',
+ isStatic: false,
+ },
+ },
+ ])
+ })
+
+ test('default slot outlet with props', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot foo="bar" :baz="qux" :foo-bar="foo-bar" />`,
+ )
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ name: { content: 'default' },
+ props: [
+ [
+ { key: { content: 'foo' }, values: [{ content: 'bar' }] },
+ { key: { content: 'baz' }, values: [{ content: 'qux' }] },
+ { key: { content: 'fooBar' }, values: [{ content: 'foo-bar' }] },
+ ],
+ ],
+ },
+ ])
+ })
+
+ test('statically named slot outlet with props', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot name="foo" foo="bar" :baz="qux" />`,
+ )
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ name: { content: 'foo' },
+ props: [
+ [
+ { key: { content: 'foo' }, values: [{ content: 'bar' }] },
+ { key: { content: 'baz' }, values: [{ content: 'qux' }] },
+ ],
+ ],
+ },
+ ])
+ })
+
+ test('statically named slot outlet with v-bind="obj"', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot name="foo" foo="bar" v-bind="obj" :baz="qux" />`,
+ )
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ name: { content: 'foo' },
+ props: [
+ [{ key: { content: 'foo' }, values: [{ content: 'bar' }] }],
+ { value: { content: 'obj', isStatic: false } },
+ [{ key: { content: 'baz' }, values: [{ content: 'qux' }] }],
+ ],
+ },
+ ])
+ })
+
+ test('statically named slot outlet with v-on', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot @click="foo" v-on="bar" :baz="qux" />`,
+ )
+ expect(code).toMatchSnapshot()
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ props: [
+ [{ key: { content: 'click' }, values: [{ content: 'foo' }] }],
+ { value: { content: 'bar' }, handler: true },
+ [{ key: { content: 'baz' }, values: [{ content: 'qux' }] }],
+ ],
+ },
+ ])
+ })
+
+ test('default slot outlet with fallback', () => {
+ const { ir, code } = compileWithSlotsOutlet(`<slot><div/></slot>`)
+ expect(code).toMatchSnapshot()
- expect(ir.template[0]).toMatchObject('<div></div>')
++ expect(ir.template[0]).toBe('<div></div>')
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: { content: 'default' },
+ fallback: {
+ type: IRNodeTypes.BLOCK,
+ dynamic: {
+ children: [{ template: 0, id: 2 }],
+ },
+ returns: [2],
+ },
+ },
+ ])
+ })
+
+ test('named slot outlet with fallback', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot name="foo"><div/></slot>`,
+ )
+ expect(code).toMatchSnapshot()
- expect(ir.template[0]).toMatchObject('<div></div>')
++ expect(ir.template[0]).toBe('<div></div>')
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: { content: 'foo' },
+ fallback: {
+ type: IRNodeTypes.BLOCK,
+ dynamic: {
+ children: [{ template: 0, id: 2 }],
+ },
+ returns: [2],
+ },
+ },
+ ])
+ })
+
+ test('default slot outlet with props & fallback', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot :foo="bar"><div/></slot>`,
+ )
+ expect(code).toMatchSnapshot()
- expect(ir.template[0]).toMatchObject('<div></div>')
++ expect(ir.template[0]).toBe('<div></div>')
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: { content: 'default' },
+ props: [[{ key: { content: 'foo' }, values: [{ content: 'bar' }] }]],
+ fallback: {
+ type: IRNodeTypes.BLOCK,
+ dynamic: {
+ children: [{ template: 0, id: 2 }],
+ },
+ returns: [2],
+ },
+ },
+ ])
+ })
+
+ test('named slot outlet with props & fallback', () => {
+ const { ir, code } = compileWithSlotsOutlet(
+ `<slot name="foo" :foo="bar"><div/></slot>`,
+ )
+ expect(code).toMatchSnapshot()
++ expect(ir.template[0]).toBe('<div></div>')
+ expect(ir.block.operation).toMatchObject([
+ {
+ type: IRNodeTypes.SLOT_OUTLET_NODE,
+ id: 0,
+ name: { content: 'foo' },
+ props: [[{ key: { content: 'foo' }, values: [{ content: 'bar' }] }]],
+ fallback: {
+ type: IRNodeTypes.BLOCK,
+ dynamic: {
+ children: [{ template: 0, id: 2 }],
+ },
+ returns: [2],
+ },
+ },
+ ])
+ })
+
+ test('error on unexpected custom directive on <slot>', () => {
+ const onError = vi.fn()
+ const source = `<slot v-foo />`
+ const index = source.indexOf('v-foo')
+ const { code } = compileWithSlotsOutlet(source, { onError })
+ expect(code).toMatchSnapshot()
+ expect(onError.mock.calls[0][0]).toMatchObject({
+ code: ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
+ loc: {
+ start: {
+ offset: index,
+ line: 1,
+ column: index + 1,
+ },
+ end: {
+ offset: index + 5,
+ line: 1,
+ column: index + 6,
+ },
+ },
+ })
+ })
+
+ test('error on unexpected custom directive with v-show on <slot>', () => {
+ const onError = vi.fn()
+ const source = `<slot v-show="ok" />`
+ const index = source.indexOf('v-show="ok"')
+ const { code } = compileWithSlotsOutlet(source, { onError })
+ expect(code).toMatchSnapshot()
+ expect(onError.mock.calls[0][0]).toMatchObject({
+ code: ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
+ loc: {
+ start: {
+ offset: index,
+ line: 1,
+ column: index + 1,
+ },
+ end: {
+ offset: index + 11,
+ line: 1,
+ column: index + 12,
+ },
+ },
+ })
+ })
+})
--- /dev/null
- genDirectiveModifiers(dir.modifiers),
+import {
+ createSimpleExpression,
+ isSimpleIdentifier,
+ toValidAssetId,
+} from '@vue/compiler-dom'
+import { extend } from '@vue/shared'
+import { genExpression } from './expression'
+import type { CodegenContext } from '../generate'
+import {
+ type CodeFragment,
+ type CodeFragmentDelimiters,
+ DELIMITERS_ARRAY,
+ NEWLINE,
+ genCall,
+ genMulti,
+} from './utils'
+import {
+ IRNodeTypes,
+ type OperationNode,
+ type WithDirectiveIRNode,
+} from '../ir'
+
+export function genDirectivesForElement(
+ id: number,
+ context: CodegenContext,
+): CodeFragment[] {
+ const dirs = filterDirectives(id, context.block.operation)
+ return dirs.length ? genWithDirective(dirs, context) : []
+}
+
+export function genWithDirective(
+ opers: WithDirectiveIRNode[],
+ context: CodegenContext,
+): CodeFragment[] {
+ const { vaporHelper } = context
+
+ const element = `n${opers[0].element}`
+ const directiveItems = opers.map(genDirective)
+ const directives = genMulti(DELIMITERS_ARRAY, ...directiveItems)
+
+ return [
+ NEWLINE,
+ ...genCall(vaporHelper('withDirectives'), element, directives),
+ ]
+
+ function genDirective({
+ dir,
+ name,
+ builtin,
+ asset,
+ }: WithDirectiveIRNode): CodeFragment[] {
+ const directive = genDirective()
+ const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
+ const argument = dir.arg && genExpression(dir.arg, context)
+ const modifiers = !!dir.modifiers.length && [
+ '{ ',
++ genDirectiveModifiers(dir.modifiers.map(m => m.content)),
+ ' }',
+ ]
+
+ return genMulti(
+ DELIMITERS_ARRAY.concat('void 0') as CodeFragmentDelimiters,
+ directive,
+ value,
+ argument,
+ modifiers,
+ )
+
+ function genDirective() {
+ if (builtin) {
+ return vaporHelper(name as any)
+ } else if (asset) {
+ return toValidAssetId(name, 'directive')
+ } else {
+ return genExpression(
+ extend(createSimpleExpression(name, false), { ast: null }),
+ context,
+ )
+ }
+ }
+ }
+}
+
+export function genDirectiveModifiers(modifiers: string[]): string {
+ return modifiers
+ .map(
+ value =>
+ `${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`,
+ )
+ .join(', ')
+}
+
+function filterDirectives(
+ id: number,
+ operations: OperationNode[],
+): WithDirectiveIRNode[] {
+ return operations.filter(
+ (oper): oper is WithDirectiveIRNode =>
+ oper.type === IRNodeTypes.WITH_DIRECTIVE && oper.element === id,
+ )
+}
--- /dev/null
- fnExpRE,
+import {
+ type SimpleExpressionNode,
- const isMemberExp = isMemberExpression(value.content, context.options)
- const isInlineStatement = !(isMemberExp || fnExpRE.test(value.content))
++ isFnExpression,
+ isMemberExpression,
+} from '@vue/compiler-dom'
+import type { CodegenContext } from '../generate'
+import type { SetDynamicEventsIRNode, SetEventIRNode } from '../ir'
+import { genExpression } from './expression'
+import {
+ type CodeFragment,
+ DELIMITERS_OBJECT_NEWLINE,
+ NEWLINE,
+ genCall,
+ genMulti,
+} from './utils'
+
+export function genSetEvent(
+ oper: SetEventIRNode,
+ context: CodegenContext,
+): CodeFragment[] {
+ const { vaporHelper } = context
+ const { element, key, keyOverride, value, modifiers, delegate, effect } = oper
+
+ const name = genName()
+ const handler = genEventHandler(context, value)
+ const eventOptions = genEventOptions()
+
+ if (delegate) {
+ // key is static
+ context.delegates.add(key.content)
+ }
+
+ return [
+ NEWLINE,
+ ...genCall(
+ vaporHelper(delegate ? 'delegate' : 'on'),
+ `n${element}`,
+ name,
+ handler,
+ eventOptions,
+ ),
+ ]
+
+ function genName(): CodeFragment[] {
+ const expr = genExpression(key, context)
+ if (keyOverride) {
+ // TODO unit test
+ const find = JSON.stringify(keyOverride[0])
+ const replacement = JSON.stringify(keyOverride[1])
+ const wrapped: CodeFragment[] = ['(', ...expr, ')']
+ return [...wrapped, ` === ${find} ? ${replacement} : `, ...wrapped]
+ } else {
+ return genExpression(key, context)
+ }
+ }
+
+ function genEventOptions(): CodeFragment[] | undefined {
+ let { options, keys, nonKeys } = modifiers
+ if (!options.length && !nonKeys.length && !keys.length && !effect) return
+
+ return genMulti(
+ DELIMITERS_OBJECT_NEWLINE,
+ !!nonKeys.length && ['modifiers: ', genArrayExpression(nonKeys)],
+ !!keys.length && ['keys: ', genArrayExpression(keys)],
+ effect && ['effect: true'],
+ ...options.map((option): CodeFragment[] => [`${option}: true`]),
+ )
+ }
+}
+
+export function genSetDynamicEvents(
+ oper: SetDynamicEventsIRNode,
+ context: CodegenContext,
+): CodeFragment[] {
+ const { vaporHelper } = context
+ return [
+ NEWLINE,
+ ...genCall(
+ vaporHelper('setDynamicEvents'),
+ `n${oper.element}`,
+ genExpression(oper.event, context),
+ ),
+ ]
+}
+
+function genArrayExpression(elements: string[]) {
+ return `[${elements.map(it => JSON.stringify(it)).join(', ')}]`
+}
+
+export function genEventHandler(
+ context: CodegenContext,
+ value: SimpleExpressionNode | undefined,
+): CodeFragment[] {
+ if (value && value.content.trim()) {
++ const isMemberExp = isMemberExpression(value, context.options)
++ const isInlineStatement = !(
++ isMemberExp || isFnExpression(value, context.options)
++ )
+
+ if (isInlineStatement) {
+ const expr = context.withId(() => genExpression(value, context), {
+ $event: null,
+ })
+ const hasMultipleStatements = value.content.includes(`;`)
+ return [
+ '() => $event => ',
+ hasMultipleStatements ? '{' : '(',
+ ...expr,
+ hasMultipleStatements ? '}' : ')',
+ ]
+ } else {
+ return ['() => ', ...genExpression(value, context)]
+ }
+ }
+
+ return ['() => {}']
+}
--- /dev/null
- if (modifiers.includes('camel')) {
+import {
+ ErrorCodes,
+ NodeTypes,
+ type SimpleExpressionNode,
+ createCompilerError,
+ createSimpleExpression,
+} from '@vue/compiler-dom'
+import { camelize, extend } from '@vue/shared'
+import type { DirectiveTransform, TransformContext } from '../transform'
+import { resolveExpression } from '../utils'
+import { isReservedProp } from './transformElement'
+
+// same-name shorthand - :arg is expanded to :arg="arg"
+export function normalizeBindShorthand(
+ arg: SimpleExpressionNode,
+ context: TransformContext,
+): SimpleExpressionNode {
+ if (arg.type !== NodeTypes.SIMPLE_EXPRESSION || !arg.isStatic) {
+ // only simple expression is allowed for same-name shorthand
+ context.options.onError(
+ createCompilerError(
+ ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
+ arg.loc,
+ ),
+ )
+ return createSimpleExpression('', true, arg.loc)
+ }
+
+ const propName = camelize(arg.content)
+ const exp = createSimpleExpression(propName, false, arg.loc)
+ exp.ast = null
+ return exp
+}
+
+export const transformVBind: DirectiveTransform = (dir, node, context) => {
+ const { loc, modifiers } = dir
+ let { exp } = dir
+ let arg = dir.arg!
++ const modifiersString = modifiers.map(s => s.content)
+
+ if (!exp) exp = normalizeBindShorthand(arg, context)
+ if (!exp.content.trim()) {
+ if (!__BROWSER__) {
+ // #10280 only error against empty expression in non-browser build
+ // because :foo in in-DOM templates will be parsed into :foo="" by the
+ // browser
+ context.options.onError(
+ createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
+ )
+ }
+ exp = createSimpleExpression('', true, loc)
+ }
+
+ exp = resolveExpression(exp)
+ arg = resolveExpression(arg)
+
+ if (arg.isStatic && isReservedProp(arg.content)) return
+
+ let camel = false
- modifier: modifiers.includes('prop')
++ if (modifiersString.includes('camel')) {
+ if (arg.isStatic) {
+ arg = extend({}, arg, { content: camelize(arg.content) })
+ } else {
+ camel = true
+ }
+ }
+
+ return {
+ key: arg,
+ value: exp,
+ loc,
+ runtimeCamelize: camel,
- : modifiers.includes('attr')
++ modifier: modifiersString.includes('prop')
+ ? '.'
++ : modifiersString.includes('attr')
+ ? '^'
+ : undefined,
+ }
+}
--- /dev/null
- (!isMemberExpression(expString, context.options) && !maybeRef)
+import {
+ BindingTypes,
+ DOMErrorCodes,
+ ElementTypes,
+ ErrorCodes,
+ NodeTypes,
+ createCompilerError,
+ createDOMCompilerError,
+ createSimpleExpression,
+ findDir,
+ findProp,
+ hasDynamicKeyVBind,
+ isMemberExpression,
+ isStaticArgOf,
+} from '@vue/compiler-dom'
+import type { DirectiveTransform } from '../transform'
+import { IRNodeTypes, type VaporHelper } from '../ir'
+
+export const transformVModel: DirectiveTransform = (dir, node, context) => {
+ const { exp, arg } = dir
+ if (!exp) {
+ context.options.onError(
+ createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc),
+ )
+ return
+ }
+
+ // we assume v-model directives are always parsed
+ // (not artificially created by a transform)
+ const rawExp = exp.loc.source
+
+ // in SFC <script setup> inline mode, the exp may have been transformed into
+ // _unref(exp)
+ const bindingType = context.options.bindingMetadata[rawExp]
+
+ // check props
+ if (
+ bindingType === BindingTypes.PROPS ||
+ bindingType === BindingTypes.PROPS_ALIASED
+ ) {
+ context.options.onError(
+ createCompilerError(ErrorCodes.X_V_MODEL_ON_PROPS, exp.loc),
+ )
+ return
+ }
+
+ const expString = exp.content
+ const maybeRef =
+ !__BROWSER__ &&
+ context.options.inline &&
+ (bindingType === BindingTypes.SETUP_LET ||
+ bindingType === BindingTypes.SETUP_REF ||
+ bindingType === BindingTypes.SETUP_MAYBE_REF)
+ if (
+ !expString.trim() ||
- modelModifiers: dir.modifiers,
++ (!isMemberExpression(exp, context.options) && !maybeRef)
+ ) {
+ context.options.onError(
+ createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc),
+ )
+ return
+ }
+
+ const isComponent = node.tagType === ElementTypes.COMPONENT
+ if (isComponent) {
+ return {
+ key: arg ? arg : createSimpleExpression('modelValue', true),
+ value: exp,
+ model: true,
++ modelModifiers: dir.modifiers.map(m => m.content),
+ }
+ }
+
+ if (dir.arg)
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
+ dir.arg.loc,
+ ),
+ )
+ const { tag } = node
+ const isCustomElement = context.options.isCustomElement(tag)
+ let runtimeDirective: VaporHelper | undefined = 'vModelText'
+ if (
+ tag === 'input' ||
+ tag === 'textarea' ||
+ tag === 'select' ||
+ isCustomElement
+ ) {
+ if (tag === 'input' || isCustomElement) {
+ const type = findProp(node, 'type')
+ if (type) {
+ if (type.type === NodeTypes.DIRECTIVE) {
+ // :type="foo"
+ runtimeDirective = 'vModelDynamic'
+ } else if (type.value) {
+ switch (type.value.content) {
+ case 'radio':
+ runtimeDirective = 'vModelRadio'
+ break
+ case 'checkbox':
+ runtimeDirective = 'vModelCheckbox'
+ break
+ case 'file':
+ runtimeDirective = undefined
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
+ dir.loc,
+ ),
+ )
+ break
+ default:
+ // text type
+ __DEV__ && checkDuplicatedValue()
+ break
+ }
+ }
+ } else if (hasDynamicKeyVBind(node)) {
+ // element has bindings with dynamic keys, which can possibly contain
+ // "type".
+ runtimeDirective = 'vModelDynamic'
+ } else {
+ // text type
+ __DEV__ && checkDuplicatedValue()
+ }
+ } else if (tag === 'select') {
+ runtimeDirective = 'vModelSelect'
+ } else {
+ // textarea
+ __DEV__ && checkDuplicatedValue()
+ }
+ } else {
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
+ dir.loc,
+ ),
+ )
+ }
+
+ context.registerOperation({
+ type: IRNodeTypes.SET_MODEL_VALUE,
+ element: context.reference(),
+ key: arg || createSimpleExpression('modelValue', true),
+ value: exp,
+ isComponent,
+ })
+
+ if (runtimeDirective)
+ context.registerOperation({
+ type: IRNodeTypes.WITH_DIRECTIVE,
+ element: context.reference(),
+ dir,
+ name: runtimeDirective,
+ builtin: true,
+ })
+
+ function checkDuplicatedValue() {
+ const value = findDir(node, 'bind')
+ if (value && isStaticArgOf(value.arg, 'value')) {
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,
+ value.loc,
+ ),
+ )
+ }
+ }
+}
import type { DefineComponent } from './apiDefineComponent'
import { markAsyncBoundary } from './helpers/useId'
import { isAsyncWrapper } from './apiAsyncComponent'
+ import type { RendererElement } from './renderer'
-export type Data = Record<string, unknown>
-
/**
* Public utility type for extracting the instance type of a component.
* Works with all valid component definition types. This is intended to replace
isArray,
isReservedProp,
} from '@vue/shared'
+import type { Data } from '@vue/runtime-shared'
import {
- type SchedulerFactory,
type SchedulerJob,
+ SchedulerJobFlags,
type SchedulerJobs,
flushPostFlushCbs,
flushPreFlushCbs,
--- /dev/null
- export function makeRender<Component = ObjectComponent | SetupFn>(
- initHost = () => {
+import {
+ type App,
++ type Component,
+ type ComponentInternalInstance,
+ type ObjectComponent,
+ type SetupFn,
+ createVaporApp,
+ defineComponent,
+} from '../src'
+import type { RawProps } from '../src/componentProps'
+
- ) {
++export interface RenderContext {
++ component: Component
++ host: HTMLElement
++ instance: ComponentInternalInstance | undefined
++ app: App
++ create: (props?: RawProps) => RenderContext
++ mount: (container?: string | ParentNode) => RenderContext
++ render: (props?: RawProps, container?: string | ParentNode) => RenderContext
++ resetHost: () => HTMLDivElement
++ html: () => string
++}
++
++export function makeRender<C = ObjectComponent | SetupFn>(
++ initHost = (): HTMLDivElement => {
+ const host = document.createElement('div')
+ host.setAttribute('id', 'host')
+ document.body.appendChild(host)
+ return host
+ },
- function define(comp: Component) {
++): (comp: C) => RenderContext {
+ let host: HTMLElement
+ function resetHost() {
+ return (host = initHost())
+ }
+
+ beforeEach(() => {
+ resetHost()
+ })
+ afterEach(() => {
+ host.remove()
+ })
+
++ function define(comp: C) {
+ const component = defineComponent(comp as any)
+ let instance: ComponentInternalInstance | undefined
+ let app: App
+
+ function render(
+ props: RawProps = {},
+ container: string | ParentNode = host,
+ ) {
+ create(props)
+ return mount(container)
+ }
+
+ function create(props: RawProps = {}) {
+ app?.unmount()
+ app = createVaporApp(component, props)
+ return res()
+ }
+
+ function mount(container: string | ParentNode = host) {
+ instance = app.mount(container)
+ return res()
+ }
+
+ function html() {
+ return host.innerHTML
+ }
+
+ const res = () => ({
+ component,
+ host,
+ instance,
+ app,
+ create,
+ mount,
+ render,
+ resetHost,
+ html,
+ })
+
+ return res()
+ }
+
+ return define
+}
--- /dev/null
- let spyIfFn: Mock<any, any>
- let spyElseFn: Mock<any, any>
+import {
+ children,
+ createIf,
+ insert,
+ nextTick,
+ ref,
+ renderEffect,
+ setText,
+ template,
+ withDirectives,
+} from '../src'
+import type { Mock } from 'vitest'
+import { makeRender } from './_utils'
+import { unmountComponent } from '../src/apiRender'
+
+const define = makeRender()
+
+describe('createIf', () => {
+ test('basic', async () => {
+ // mock this template:
+ // <div>
+ // <p v-if="counter">{{counter}}</p>
+ // <p v-else>zero</p>
+ // </div>
+
++ let spyIfFn: Mock<any>
++ let spyElseFn: Mock<any>
+ const count = ref(0)
+
+ const spyConditionFn = vi.fn(() => count.value)
+
+ // templates can be reused through caching.
+ const t0 = template('<div></div>')
+ const t1 = template('<p></p>')
+ const t2 = template('<p>zero</p>')
+
+ const { host } = define(() => {
+ const n0 = t0()
+
+ insert(
+ createIf(
+ spyConditionFn,
+ // v-if
+ (spyIfFn ||= vi.fn(() => {
+ const n2 = t1()
+ renderEffect(() => {
+ setText(n2, count.value)
+ })
+ return n2
+ })),
+ // v-else
+ (spyElseFn ||= vi.fn(() => {
+ const n4 = t2()
+ return n4
+ })),
+ ),
+ n0 as any as ParentNode,
+ )
+ return n0
+ }).render()
+
+ expect(host.innerHTML).toBe('<div><p>zero</p><!--if--></div>')
+ expect(spyConditionFn).toHaveBeenCalledTimes(1)
+ expect(spyIfFn!).toHaveBeenCalledTimes(0)
+ expect(spyElseFn!).toHaveBeenCalledTimes(1)
+
+ count.value++
+ await nextTick()
+ expect(host.innerHTML).toBe('<div><p>1</p><!--if--></div>')
+ expect(spyConditionFn).toHaveBeenCalledTimes(2)
+ expect(spyIfFn!).toHaveBeenCalledTimes(1)
+ expect(spyElseFn!).toHaveBeenCalledTimes(1)
+
+ count.value++
+ await nextTick()
+ expect(host.innerHTML).toBe('<div><p>2</p><!--if--></div>')
+ expect(spyConditionFn).toHaveBeenCalledTimes(3)
+ expect(spyIfFn!).toHaveBeenCalledTimes(1)
+ expect(spyElseFn!).toHaveBeenCalledTimes(1)
+
+ count.value = 0
+ await nextTick()
+ expect(host.innerHTML).toBe('<div><p>zero</p><!--if--></div>')
+ expect(spyConditionFn).toHaveBeenCalledTimes(4)
+ expect(spyIfFn!).toHaveBeenCalledTimes(1)
+ expect(spyElseFn!).toHaveBeenCalledTimes(2)
+ })
+
+ test('should handle nested template', async () => {
+ // mock this template:
+ // <template v-if="ok1">
+ // Hello <template v-if="ok2">Vapor</template>
+ // </template>
+
+ const ok1 = ref(true)
+ const ok2 = ref(true)
+
+ const t0 = template('Vapor')
+ const t1 = template('Hello ')
+ const { host } = define(() => {
+ const n1 = createIf(
+ () => ok1.value,
+ () => {
+ const n2 = t1()
+ const n3 = createIf(
+ () => ok2.value,
+ () => {
+ const n4 = t0()
+ return n4
+ },
+ )
+ return [n2, n3]
+ },
+ )
+ return n1
+ }).render()
+
+ expect(host.innerHTML).toBe('Hello Vapor<!--if--><!--if-->')
+
+ ok1.value = false
+ await nextTick()
+ expect(host.innerHTML).toBe('<!--if-->')
+
+ ok1.value = true
+ await nextTick()
+ expect(host.innerHTML).toBe('Hello Vapor<!--if--><!--if-->')
+
+ ok2.value = false
+ await nextTick()
+ expect(host.innerHTML).toBe('Hello <!--if--><!--if-->')
+
+ ok1.value = false
+ await nextTick()
+ expect(host.innerHTML).toBe('<!--if-->')
+ })
+
+ test('should work with directive hooks', async () => {
+ const calls: string[] = []
+ const show1 = ref(true)
+ const show2 = ref(true)
+ const update = ref(0)
+
+ const spyConditionFn1 = vi.fn(() => show1.value)
+ const spyConditionFn2 = vi.fn(() => show2.value)
+
+ const vDirective: any = {
+ created: (el: any, { value }: any) => calls.push(`${value} created`),
+ beforeMount: (el: any, { value }: any) =>
+ calls.push(`${value} beforeMount`),
+ mounted: (el: any, { value }: any) => calls.push(`${value} mounted`),
+ beforeUpdate: (el: any, { value }: any) =>
+ calls.push(`${value} beforeUpdate`),
+ updated: (el: any, { value }: any) => calls.push(`${value} updated`),
+ beforeUnmount: (el: any, { value }: any) =>
+ calls.push(`${value} beforeUnmount`),
+ unmounted: (el: any, { value }: any) => calls.push(`${value} unmounted`),
+ }
+
+ const t0 = template('<p></p>')
+ const { instance } = define(() => {
+ const n1 = createIf(
+ spyConditionFn1,
+ () => {
+ const n2 = t0()
+ withDirectives(children(n2, 0), [
+ [vDirective, () => (update.value, '1')],
+ ])
+ return n2
+ },
+ () =>
+ createIf(
+ spyConditionFn2,
+ () => {
+ const n2 = t0()
+ withDirectives(children(n2, 0), [[vDirective, () => '2']])
+ return n2
+ },
+ () => {
+ const n2 = t0()
+ withDirectives(children(n2, 0), [[vDirective, () => '3']])
+ return n2
+ },
+ ),
+ )
+ return [n1]
+ }).render()
+
+ await nextTick()
+ expect(calls).toEqual(['1 created', '1 beforeMount', '1 mounted'])
+ calls.length = 0
+ expect(spyConditionFn1).toHaveBeenCalledTimes(1)
+ expect(spyConditionFn2).toHaveBeenCalledTimes(0)
+
+ show1.value = false
+ await nextTick()
+ expect(calls).toEqual([
+ '1 beforeUnmount',
+ '2 created',
+ '2 beforeMount',
+ '1 unmounted',
+ '2 mounted',
+ ])
+ calls.length = 0
+ expect(spyConditionFn1).toHaveBeenCalledTimes(2)
+ expect(spyConditionFn2).toHaveBeenCalledTimes(1)
+
+ show2.value = false
+ await nextTick()
+ expect(calls).toEqual([
+ '2 beforeUnmount',
+ '3 created',
+ '3 beforeMount',
+ '2 unmounted',
+ '3 mounted',
+ ])
+ calls.length = 0
+ expect(spyConditionFn1).toHaveBeenCalledTimes(2)
+ expect(spyConditionFn2).toHaveBeenCalledTimes(2)
+
+ show1.value = true
+ await nextTick()
+ expect(calls).toEqual([
+ '3 beforeUnmount',
+ '1 created',
+ '1 beforeMount',
+ '3 unmounted',
+ '1 mounted',
+ ])
+ calls.length = 0
+ expect(spyConditionFn1).toHaveBeenCalledTimes(3)
+ expect(spyConditionFn2).toHaveBeenCalledTimes(2)
+
+ update.value++
+ await nextTick()
+ expect(calls).toEqual(['1 beforeUpdate', '1 updated'])
+ calls.length = 0
+ expect(spyConditionFn1).toHaveBeenCalledTimes(3)
+ expect(spyConditionFn2).toHaveBeenCalledTimes(2)
+
+ unmountComponent(instance!)
+ expect(calls).toEqual(['1 beforeUnmount', '1 unmounted'])
+ expect(spyConditionFn1).toHaveBeenCalledTimes(3)
+ expect(spyConditionFn2).toHaveBeenCalledTimes(2)
+ })
+})
--- /dev/null
- type BaseWatchErrorCodes,
- type BaseWatchOptions,
+import {
- baseWatch,
- getCurrentScope,
++ type WatchOptions as BaseWatchOptions,
+ type ComputedRef,
+ type DebuggerOptions,
+ type Ref,
- import { EMPTY_OBJ, extend, isFunction, remove } from '@vue/shared'
++ watch as baseWatch,
+} from '@vue/reactivity'
- type SchedulerFactory,
- createVaporPostScheduler,
- createVaporPreScheduler,
- createVaporSyncScheduler,
++import { EMPTY_OBJ, extend, isFunction } from '@vue/shared'
+import { currentInstance } from './component'
+import {
- import { handleError as handleErrorWithInstance } from './errorHandling'
++ type SchedulerJob,
++ VaporSchedulerJobFlags,
++ queueJob,
++ queuePostFlushCb,
+} from './scheduler'
- function getScheduler(flush: WatchOptionsBase['flush']): SchedulerFactory {
- if (flush === 'post') {
- return createVaporPostScheduler
- }
- if (flush === 'sync') {
- return createVaporSyncScheduler
- }
- // default: 'pre'
- return createVaporPreScheduler
- }
-
++import { callWithAsyncErrorHandling } from './errorHandling'
+import { warn } from './warning'
+
+export type WatchEffect = (onCleanup: OnCleanup) => void
+
+export type WatchSource<T = any> = Ref<T> | ComputedRef<T> | (() => T)
+
+export type WatchCallback<V = any, OV = any> = (
+ value: V,
+ oldValue: OV,
+ onCleanup: OnCleanup,
+) => any
+
+type MapSources<T, Immediate> = {
+ [K in keyof T]: T[K] extends WatchSource<infer V>
+ ? Immediate extends true
+ ? V | undefined
+ : V
+ : T[K] extends object
+ ? Immediate extends true
+ ? T[K] | undefined
+ : T[K]
+ : never
+}
+
+type OnCleanup = (cleanupFn: () => void) => void
+
+export interface WatchOptionsBase extends DebuggerOptions {
+ flush?: 'pre' | 'post' | 'sync'
+}
+
+export interface WatchOptions<Immediate = boolean> extends WatchOptionsBase {
+ immediate?: Immediate
+ deep?: boolean
+ once?: boolean
+}
+
+export type WatchStopHandle = () => void
+
+// Simple effect.
+export function watchEffect(
+ effect: WatchEffect,
+ options?: WatchOptionsBase,
+): WatchStopHandle {
+ return doWatch(effect, null, options)
+}
+
+export function watchPostEffect(
+ effect: WatchEffect,
+ options?: DebuggerOptions,
+): WatchStopHandle {
+ return doWatch(
+ effect,
+ null,
+ __DEV__ ? extend({}, options as any, { flush: 'post' }) : { flush: 'post' },
+ )
+}
+
+export function watchSyncEffect(
+ effect: WatchEffect,
+ options?: DebuggerOptions,
+): WatchStopHandle {
+ return doWatch(
+ effect,
+ null,
+ __DEV__ ? extend({}, options as any, { flush: 'sync' }) : { flush: 'sync' },
+ )
+}
+
+type MultiWatchSources = (WatchSource<unknown> | object)[]
+
+// overload: single source + cb
+export function watch<T, Immediate extends Readonly<boolean> = false>(
+ source: WatchSource<T>,
+ cb: WatchCallback<T, Immediate extends true ? T | undefined : T>,
+ options?: WatchOptions<Immediate>,
+): WatchStopHandle
+
+// overload: array of multiple sources + cb
+export function watch<
+ T extends MultiWatchSources,
+ Immediate extends Readonly<boolean> = false,
+>(
+ sources: [...T],
+ cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
+ options?: WatchOptions<Immediate>,
+): WatchStopHandle
+
+// overload: multiple sources w/ `as const`
+// watch([foo, bar] as const, () => {})
+// somehow [...T] breaks when the type is readonly
+export function watch<
+ T extends Readonly<MultiWatchSources>,
+ Immediate extends Readonly<boolean> = false,
+>(
+ source: T,
+ cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
+ options?: WatchOptions<Immediate>,
+): WatchStopHandle
+
+// overload: watching reactive object w/ cb
+export function watch<
+ T extends object,
+ Immediate extends Readonly<boolean> = false,
+>(
+ source: T,
+ cb: WatchCallback<T, Immediate extends true ? T | undefined : T>,
+ options?: WatchOptions<Immediate>,
+): WatchStopHandle
+
+// implementation
+export function watch<T = any, Immediate extends Readonly<boolean> = false>(
+ source: T | WatchSource<T>,
+ cb: any,
+ options?: WatchOptions<Immediate>,
+): WatchStopHandle {
+ if (__DEV__ && !isFunction(cb)) {
+ warn(
+ `\`watch(fn, options?)\` signature has been moved to a separate API. ` +
+ `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
+ `supports \`watch(source, cb, options?) signature.`,
+ )
+ }
+ return doWatch(source as any, cb, options)
+}
+
- const extendOptions: BaseWatchOptions = {}
+function doWatch(
+ source: WatchSource | WatchSource[] | WatchEffect | object,
+ cb: WatchCallback | null,
+ options: WatchOptions = EMPTY_OBJ,
+): WatchStopHandle {
+ const { immediate, deep, flush, once } = options
+
+ if (__DEV__ && !cb) {
+ if (immediate !== undefined) {
+ warn(
+ `watch() "immediate" option is only respected when using the ` +
+ `watch(source, callback, options?) signature.`,
+ )
+ }
+ if (deep !== undefined) {
+ warn(
+ `watch() "deep" option is only respected when using the ` +
+ `watch(source, callback, options?) signature.`,
+ )
+ }
+ if (once !== undefined) {
+ warn(
+ `watch() "once" option is only respected when using the ` +
+ `watch(source, callback, options?) signature.`,
+ )
+ }
+ }
+
- if (__DEV__) extendOptions.onWarn = warn
++ const baseWatchOptions: BaseWatchOptions = extend({}, options)
+
- extendOptions.onError = (err: unknown, type: BaseWatchErrorCodes) =>
- handleErrorWithInstance(err, instance, type)
- extendOptions.scheduler = getScheduler(flush)(instance)
++ if (__DEV__) baseWatchOptions.onWarn = warn
+
+ let ssrCleanup: (() => void)[] | undefined
+ // TODO: SSR
+ // if (__SSR__ && isInSSRComponentSetup) {
+ // if (flush === 'sync') {
+ // const ctx = useSSRContext()!
+ // ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = [])
+ // } else if (!cb || immediate) {
+ // // immediately watch or watchEffect
+ // extendOptions.once = true
+ // } else {
+ // // watch(source, cb)
+ // return NOOP
+ // }
+ // }
+
+ const instance = currentInstance
++ baseWatchOptions.call = (fn, type, args) =>
++ callWithAsyncErrorHandling(fn, instance, type, args)
+
- const effect = baseWatch(source, cb, extend({}, options, extendOptions))
- const scope = getCurrentScope()
- const unwatch = () => {
- effect!.stop()
- if (scope) {
- remove(scope.effects, effect)
++ // scheduler
++ let isPre = false
++ if (flush === 'post') {
++ baseWatchOptions.scheduler = job => {
++ queuePostFlushCb(job)
++ }
++ } else if (flush !== 'sync') {
++ // default: 'pre'
++ isPre = true
++ baseWatchOptions.scheduler = (job, isFirstRun) => {
++ if (isFirstRun) {
++ job()
++ } else {
++ queueJob(job)
++ }
++ }
++ }
+
- if (__SSR__ && ssrCleanup) ssrCleanup.push(unwatch)
- return unwatch
++ baseWatchOptions.augmentJob = (job: SchedulerJob) => {
++ // important: mark the job as a watcher callback so that scheduler knows
++ // it is allowed to self-trigger (#1727)
++ if (cb) {
++ job.flags! |= VaporSchedulerJobFlags.ALLOW_RECURSE
++ }
++ if (isPre) {
++ job.flags! |= VaporSchedulerJobFlags.PRE
++ if (instance) {
++ job.id = instance.uid
++ ;(job as SchedulerJob).i = instance
++ }
+ }
+ }
+
++ const watchHandle = baseWatch(source, cb, baseWatchOptions)
++
++ if (__SSR__ && ssrCleanup) ssrCleanup.push(watchHandle)
++ return watchHandle
+}
--- /dev/null
- type SchedulerJob,
+import { invokeArrayFns, isBuiltInDirective, isFunction } from '@vue/shared'
+import {
+ type ComponentInternalInstance,
+ currentInstance,
+ isVaporComponent,
+ setCurrentInstance,
+} from './component'
+import {
+ EffectFlags,
+ ReactiveEffect,
- import { queueJob, queuePostFlushCb } from './scheduler'
+ getCurrentScope,
+ pauseTracking,
+ resetTracking,
+ traverse,
+} from '@vue/reactivity'
+import {
+ VaporErrorCodes,
+ callWithAsyncErrorHandling,
+ callWithErrorHandling,
+} from './errorHandling'
++import { type SchedulerJob, queueJob, queuePostFlushCb } from './scheduler'
+import { warn } from './warning'
+import { type BlockEffectScope, isRenderEffectScope } from './blockEffectScope'
+import { normalizeBlock } from './dom/element'
+
+export type DirectiveModifiers<M extends string = string> = Record<M, boolean>
+
+export interface DirectiveBinding<T = any, V = any, M extends string = string> {
+ instance: ComponentInternalInstance
+ source?: () => V
+ value: V
+ oldValue: V | null
+ arg?: string
+ modifiers?: DirectiveModifiers<M>
+ dir: ObjectDirective<T, V, M>
+}
+
+export type DirectiveBindingsMap = Map<Node, DirectiveBinding[]>
+
+export type DirectiveHook<
+ T = any | null,
+ V = any,
+ M extends string = string,
+> = (node: T, binding: DirectiveBinding<T, V, M>) => void
+
+// create node -> `created` -> node operation -> `beforeMount` -> node mounted -> `mounted`
+// effect update -> `beforeUpdate` -> node updated -> `updated`
+// `beforeUnmount`-> node unmount -> `unmounted`
+export type DirectiveHookName =
+ | 'created'
+ | 'beforeMount'
+ | 'mounted'
+ | 'beforeUpdate'
+ | 'updated'
+ | 'beforeUnmount'
+ | 'unmounted'
+export type ObjectDirective<T = any, V = any, M extends string = string> = {
+ [K in DirectiveHookName]?: DirectiveHook<T, V, M> | undefined
+} & {
+ /** Watch value deeply */
+ deep?: boolean | number
+}
+
+export type FunctionDirective<
+ T = any,
+ V = any,
+ M extends string = string,
+> = DirectiveHook<T, V, M>
+
+export type Directive<T = any, V = any, M extends string = string> =
+ | ObjectDirective<T, V, M>
+ | FunctionDirective<T, V, M>
+
+export function validateDirectiveName(name: string): void {
+ if (isBuiltInDirective(name)) {
+ warn('Do not use built-in directive ids as custom directive id: ' + name)
+ }
+}
+
+export type DirectiveArguments = Array<
+ | [Directive | undefined]
+ | [Directive | undefined, () => any]
+ | [Directive | undefined, () => any, argument: string]
+ | [
+ Directive | undefined,
+ value: () => any,
+ argument: string,
+ modifiers: DirectiveModifiers,
+ ]
+>
+
+export function withDirectives<T extends ComponentInternalInstance | Node>(
+ nodeOrComponent: T,
+ directives: DirectiveArguments,
+): T {
+ if (!currentInstance) {
+ __DEV__ && warn(`withDirectives can only be used inside render functions.`)
+ return nodeOrComponent
+ }
+
+ let node: Node
+ if (isVaporComponent(nodeOrComponent)) {
+ const root = getComponentNode(nodeOrComponent)
+ if (!root) return nodeOrComponent
+ node = root
+ } else {
+ node = nodeOrComponent
+ }
+
+ let bindings: DirectiveBinding[]
+ const instance = currentInstance!
+ const parentScope = getCurrentScope() as BlockEffectScope
+
+ if (__DEV__ && !isRenderEffectScope(parentScope)) {
+ warn(`Directives should be used inside of RenderEffectScope.`)
+ }
+
+ const directivesMap = (parentScope.dirs ||= new Map())
+ if (!(bindings = directivesMap.get(node))) {
+ directivesMap.set(node, (bindings = []))
+ }
+
+ for (const directive of directives) {
+ let [dir, source, arg, modifiers] = directive
+ if (!dir) continue
+ if (isFunction(dir)) {
+ dir = {
+ mounted: dir,
+ updated: dir,
+ } satisfies ObjectDirective
+ }
+
+ const binding: DirectiveBinding = {
+ dir,
+ instance,
+ value: null, // set later
+ oldValue: undefined,
+ arg,
+ modifiers,
+ }
+
+ if (source) {
+ if (dir.deep) {
+ const deep = dir.deep === true ? undefined : dir.deep
+ const baseSource = source
+ source = () => traverse(baseSource(), deep)
+ }
+
+ const effect = new ReactiveEffect(() =>
+ callWithErrorHandling(
+ source!,
+ instance,
+ VaporErrorCodes.RENDER_FUNCTION,
+ ),
+ )
+ const triggerRenderingUpdate = createRenderingUpdateTrigger(
+ instance,
+ effect,
+ )
+ effect.scheduler = () => queueJob(triggerRenderingUpdate)
+
+ binding.source = effect.run.bind(effect)
+ }
+
+ bindings.push(binding)
+
+ callDirectiveHook(node, binding, instance, 'created')
+ }
+
+ return nodeOrComponent
+}
+
+function getComponentNode(component: ComponentInternalInstance) {
+ if (!component.block) return
+
+ const nodes = normalizeBlock(component.block)
+ if (nodes.length !== 1) {
+ warn(
+ `Runtime directive used on component with non-element root node. ` +
+ `The directives will not function as intended.`,
+ )
+ return
+ }
+
+ return nodes[0]
+}
+
+export function invokeDirectiveHook(
+ instance: ComponentInternalInstance | null,
+ name: DirectiveHookName,
+ scope: BlockEffectScope,
+): void {
+ const { dirs } = scope
+ if (name === 'mounted') scope.im = true
+ if (!dirs) return
+ const iterator = dirs.entries()
+ for (const [node, bindings] of iterator) {
+ for (const binding of bindings) {
+ callDirectiveHook(node, binding, instance, name)
+ }
+ }
+}
+
+function callDirectiveHook(
+ node: Node,
+ binding: DirectiveBinding,
+ instance: ComponentInternalInstance | null,
+ name: DirectiveHookName,
+) {
+ if (name === 'beforeUpdate') binding.oldValue = binding.value
+ const { dir } = binding
+ const hook = dir[name]
+ if (!hook) return
+
+ const newValue = binding.source ? binding.source() : undefined
+ binding.value = newValue
+ // disable tracking inside all lifecycle hooks
+ // since they can potentially be called inside effects.
+ pauseTracking()
+ callWithAsyncErrorHandling(hook, instance, VaporErrorCodes.DIRECTIVE_HOOK, [
+ node,
+ binding,
+ ])
+ resetTracking()
+}
+
+export function createRenderingUpdateTrigger(
+ instance: ComponentInternalInstance,
+ effect: ReactiveEffect,
+): SchedulerJob {
+ job.id = instance.uid
+ return job
+ function job() {
+ if (!(effect.flags & EffectFlags.ACTIVE) || !effect.dirty) {
+ return
+ }
+
+ if (instance.isMounted && !instance.isUpdating) {
+ instance.isUpdating = true
+ const reset = setCurrentInstance(instance)
+
+ const { bu, u, scope } = instance
+ const { dirs } = scope
+ // beforeUpdate hook
+ if (bu) {
+ invokeArrayFns(bu)
+ }
+ invokeDirectiveHook(instance, 'beforeUpdate', scope)
+
+ queuePostFlushCb(() => {
+ instance.isUpdating = false
+ const reset = setCurrentInstance(instance)
+ if (dirs) {
+ invokeDirectiveHook(instance, 'updated', scope)
+ }
+ // updated hook
+ if (u) {
+ queuePostFlushCb(u)
+ }
+ reset()
+ })
+ reset()
+ }
+ }
+}
--- /dev/null
- import {
- type Ref,
- type SchedulerJob,
- isRef,
- onScopeDispose,
- } from '@vue/reactivity'
++import { type Ref, isRef, onScopeDispose } from '@vue/reactivity'
+import {
+ type ComponentInternalInstance,
+ currentInstance,
+ isVaporComponent,
+} from '../component'
+import { VaporErrorCodes, callWithErrorHandling } from '../errorHandling'
+import {
+ EMPTY_OBJ,
+ hasOwn,
+ isArray,
+ isFunction,
+ isString,
+ remove,
+} from '@vue/shared'
+import { warn } from '../warning'
- import { queuePostFlushCb } from '../scheduler'
++import { type SchedulerJob, queuePostFlushCb } from '../scheduler'
+
+export type NodeRef = string | Ref | ((ref: Element) => void)
+export type RefEl = Element | ComponentInternalInstance
+
+/**
+ * Function for handling a template ref
+ */
+export function setRef(
+ el: RefEl,
+ ref: NodeRef,
+ oldRef?: NodeRef,
+ refFor = false,
+): NodeRef | undefined {
+ if (!currentInstance) return
+ const { setupState, isUnmounted } = currentInstance
+
+ if (isUnmounted) {
+ return
+ }
+
+ const refValue = isVaporComponent(el) ? el.exposed || el : el
+
+ const refs =
+ currentInstance.refs === EMPTY_OBJ
+ ? (currentInstance.refs = {})
+ : currentInstance.refs
+
+ // dynamic ref changed. unset old ref
+ if (oldRef != null && oldRef !== ref) {
+ if (isString(oldRef)) {
+ refs[oldRef] = null
+ if (hasOwn(setupState, oldRef)) {
+ setupState[oldRef] = null
+ }
+ } else if (isRef(oldRef)) {
+ oldRef.value = null
+ }
+ }
+
+ if (isFunction(ref)) {
+ const invokeRefSetter = (value?: Element | Record<string, any>) => {
+ callWithErrorHandling(
+ ref,
+ currentInstance,
+ VaporErrorCodes.FUNCTION_REF,
+ [value, refs],
+ )
+ }
+
+ invokeRefSetter(refValue)
+ onScopeDispose(() => invokeRefSetter())
+ } else {
+ const _isString = isString(ref)
+ const _isRef = isRef(ref)
+ let existing: unknown
+
+ if (_isString || _isRef) {
+ const doSet: SchedulerJob = () => {
+ if (refFor) {
+ existing = _isString
+ ? hasOwn(setupState, ref)
+ ? setupState[ref]
+ : refs[ref]
+ : ref.value
+
+ if (!isArray(existing)) {
+ existing = [refValue]
+ if (_isString) {
+ refs[ref] = existing
+ if (hasOwn(setupState, ref)) {
+ setupState[ref] = refs[ref]
+ // if setupState[ref] is a reactivity ref,
+ // the existing will also become reactivity too
+ // need to get the Proxy object by resetting
+ existing = setupState[ref]
+ }
+ } else {
+ ref.value = existing
+ }
+ } else if (!existing.includes(refValue)) {
+ existing.push(refValue)
+ }
+ } else if (_isString) {
+ refs[ref] = refValue
+ if (hasOwn(setupState, ref)) {
+ setupState[ref] = refValue
+ }
+ } else if (_isRef) {
+ ref.value = refValue
+ } else if (__DEV__) {
+ warn('Invalid template ref type:', ref, `(${typeof ref})`)
+ }
+ }
+ doSet.id = -1
+ queuePostFlushCb(doSet)
+
+ onScopeDispose(() => {
+ queuePostFlushCb(() => {
+ if (isArray(existing)) {
+ remove(existing, refValue)
+ } else if (_isString) {
+ refs[ref] = null
+ if (hasOwn(setupState, ref)) {
+ setupState[ref] = null
+ }
+ } else if (_isRef) {
+ ref.value = null
+ }
+ })
+ })
+ } else if (__DEV__) {
+ warn('Invalid template ref type:', ref, `(${typeof ref})`)
+ }
+ }
+ return ref
+}
--- /dev/null
- import {
- BaseWatchErrorCodes,
- pauseTracking,
- resetTracking,
- } from '@vue/reactivity'
+// These codes originate from a file of the same name in runtime-core,
+// duplicated during Vapor's early development to ensure its independence.
+// The ultimate aim is to uncouple this replicated code and
+// facilitate its shared use between two runtimes.
+
+import type { ComponentInternalInstance } from './component'
+import { isFunction, isPromise } from '@vue/shared'
+import { warn } from './warning'
+import { VaporLifecycleHooks } from './enums'
- export type ErrorTypes =
- | VaporLifecycleHooks
- | VaporErrorCodes
- | BaseWatchErrorCodes
++import { WatchErrorCodes, pauseTracking, resetTracking } from '@vue/reactivity'
+
+// contexts where user provided function may be executed, in addition to
+// lifecycle hooks.
+export enum VaporErrorCodes {
+ SETUP_FUNCTION,
+ RENDER_FUNCTION,
+ // The error codes for the watch have been transferred to the reactivity
+ // package along with baseWatch to maintain code compatibility. Hence,
+ // it is essential to keep these values unchanged.
+ // WATCH_GETTER,
+ // WATCH_CALLBACK,
+ // WATCH_CLEANUP,
+ NATIVE_EVENT_HANDLER = 5,
+ COMPONENT_EVENT_HANDLER,
+ VNODE_HOOK,
+ DIRECTIVE_HOOK,
+ TRANSITION_HOOK,
+ APP_ERROR_HANDLER,
+ APP_WARN_HANDLER,
+ FUNCTION_REF,
+ ASYNC_COMPONENT_LOADER,
+ SCHEDULER,
+}
+
- [BaseWatchErrorCodes.WATCH_GETTER]: 'watcher getter',
- [BaseWatchErrorCodes.WATCH_CALLBACK]: 'watcher callback',
- [BaseWatchErrorCodes.WATCH_CLEANUP]: 'watcher cleanup function',
++export type ErrorTypes = VaporLifecycleHooks | VaporErrorCodes | WatchErrorCodes
+
+export const ErrorTypeStrings: Record<ErrorTypes, string> = {
+ // [VaporLifecycleHooks.SERVER_PREFETCH]: 'serverPrefetch hook',
+ [VaporLifecycleHooks.BEFORE_MOUNT]: 'beforeMount hook',
+ [VaporLifecycleHooks.MOUNTED]: 'mounted hook',
+ [VaporLifecycleHooks.BEFORE_UPDATE]: 'beforeUpdate hook',
+ [VaporLifecycleHooks.UPDATED]: 'updated',
+ [VaporLifecycleHooks.BEFORE_UNMOUNT]: 'beforeUnmount hook',
+ [VaporLifecycleHooks.UNMOUNTED]: 'unmounted hook',
+ [VaporLifecycleHooks.ACTIVATED]: 'activated hook',
+ [VaporLifecycleHooks.DEACTIVATED]: 'deactivated hook',
+ [VaporLifecycleHooks.ERROR_CAPTURED]: 'errorCaptured hook',
+ [VaporLifecycleHooks.RENDER_TRACKED]: 'renderTracked hook',
+ [VaporLifecycleHooks.RENDER_TRIGGERED]: 'renderTriggered hook',
+ [VaporErrorCodes.SETUP_FUNCTION]: 'setup function',
+ [VaporErrorCodes.RENDER_FUNCTION]: 'render function',
++ [WatchErrorCodes.WATCH_GETTER]: 'watcher getter',
++ [WatchErrorCodes.WATCH_CALLBACK]: 'watcher callback',
++ [WatchErrorCodes.WATCH_CLEANUP]: 'watcher cleanup function',
+ [VaporErrorCodes.NATIVE_EVENT_HANDLER]: 'native event handler',
+ [VaporErrorCodes.COMPONENT_EVENT_HANDLER]: 'component event handler',
+ [VaporErrorCodes.VNODE_HOOK]: 'vnode hook',
+ [VaporErrorCodes.DIRECTIVE_HOOK]: 'directive hook',
+ [VaporErrorCodes.TRANSITION_HOOK]: 'transition hook',
+ [VaporErrorCodes.APP_ERROR_HANDLER]: 'app errorHandler',
+ [VaporErrorCodes.APP_WARN_HANDLER]: 'app warnHandler',
+ [VaporErrorCodes.FUNCTION_REF]: 'ref function',
+ [VaporErrorCodes.ASYNC_COMPONENT_LOADER]: 'async component loader',
+ [VaporErrorCodes.SCHEDULER]:
+ 'scheduler flush. This is likely a Vue internals bug. ' +
+ 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core',
+}
+
+export function callWithErrorHandling(
+ fn: Function,
+ instance: ComponentInternalInstance | null,
+ type: ErrorTypes,
+ args?: unknown[],
+): any {
+ let res
+ try {
+ res = args ? fn(...args) : fn()
+ } catch (err) {
+ handleError(err, instance, type)
+ }
+ return res
+}
+
+export function callWithAsyncErrorHandling<F extends Function | Function[]>(
+ fn: F,
+ instance: ComponentInternalInstance | null,
+ type: ErrorTypes,
+ args?: unknown[],
+): F extends Function ? any : any[] {
+ if (isFunction(fn)) {
+ const res = callWithErrorHandling(fn, instance, type, args)
+ if (res && isPromise(res)) {
+ res.catch(err => {
+ handleError(err, instance, type)
+ })
+ }
+ return res
+ }
+
+ const values = []
+ for (let i = 0; i < fn.length; i++) {
+ values.push(callWithAsyncErrorHandling(fn[i], instance, type, args))
+ }
+ return values
+}
+
+export function handleError(
+ err: unknown,
+ instance: ComponentInternalInstance | null,
+ type: ErrorTypes,
+ throwInDev = true,
+): void {
+ if (instance) {
+ let cur = instance.parent
+ // in production the hook receives only the error code
+ const errorInfo = __DEV__
+ ? ErrorTypeStrings[type]
+ : `https://vuejs.org/errors/#runtime-${type}`
+ while (cur) {
+ const errorCapturedHooks = 'ec' in cur ? cur.ec : null
+ if (errorCapturedHooks) {
+ for (let i = 0; i < errorCapturedHooks.length; i++) {
+ if (errorCapturedHooks[i](err, instance, errorInfo) === false) {
+ return
+ }
+ }
+ }
+ cur = cur.parent
+ }
+
+ // app-level handling
+ const appErrorHandler = instance.appContext.config.errorHandler
+ if (appErrorHandler) {
+ pauseTracking()
+ callWithErrorHandling(
+ appErrorHandler,
+ null,
+ VaporErrorCodes.APP_ERROR_HANDLER,
+ [err, instance, errorInfo],
+ )
+ resetTracking()
+ return
+ }
+ }
+ logError(err, type, throwInDev)
+}
+
+function logError(err: unknown, type: ErrorTypes, throwInDev = true) {
+ if (__DEV__) {
+ const info = ErrorTypeStrings[type]
+ warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`)
+ // crash in dev by default so it's more noticeable
+ if (throwInDev) {
+ throw err
+ } else if (!__TEST__) {
+ console.error(err)
+ }
+ } else {
+ // recover in prod to reduce the impact on end-user
+ console.error(err)
+ }
+}
--- /dev/null
- type Component,
+// Core API ------------------------------------------------------------------
+
+export const version: string = __VERSION__
+export {
+ // core
+ type Ref,
+ type DebuggerEvent,
+ TrackOpTypes,
+ TriggerOpTypes,
+ reactive,
+ ref,
+ readonly,
+ computed,
+ // utilities
+ unref,
+ proxyRefs,
+ isRef,
+ toRef,
+ toValue,
+ toRefs,
+ isProxy,
+ isReactive,
+ isReadonly,
+ isShallow,
+ // advanced
+ customRef,
+ triggerRef,
+ shallowRef,
+ shallowReactive,
+ shallowReadonly,
+ markRaw,
+ toRaw,
+ // effect
+ stop,
+ ReactiveEffect,
+ onEffectCleanup,
+ // effect scope
+ effectScope,
+ EffectScope,
+ getCurrentScope,
+ onScopeDispose,
+ // baseWatch
+ onWatcherCleanup,
+ getCurrentWatcher,
+} from '@vue/reactivity'
+
+import { NOOP } from '@vue/shared'
+import { warn as _warn } from './warning'
+export const warn = (__DEV__ ? _warn : NOOP) as typeof _warn
+
+export { nextTick } from './scheduler'
+export {
+ getCurrentInstance,
+ type ComponentInternalInstance,
++ type Component as Component,
+ type ObjectComponent,
+ type FunctionalComponent,
+ type SetupFn,
+} from './component'
+export { createSlot } from './componentSlots'
+export { renderEffect } from './renderEffect'
+export {
+ watch,
+ watchEffect,
+ watchPostEffect,
+ watchSyncEffect,
+ type WatchEffect,
+ type WatchOptions,
+ type WatchOptionsBase,
+ type WatchCallback,
+ type WatchSource,
+ type WatchStopHandle,
+} from './apiWatch'
+export {
+ withDirectives,
+ type Directive,
+ type DirectiveBinding,
+ type DirectiveHook,
+ type ObjectDirective,
+ type FunctionDirective,
+ type DirectiveArguments,
+ type DirectiveModifiers,
+} from './directives'
+
+export { template, children, next } from './dom/template'
+export { insert, prepend, remove, createTextNode } from './dom/element'
+export { setStyle } from './dom/style'
+export {
+ setText,
+ setHtml,
+ setClass,
+ setAttr,
+ setDOMProp,
+ setDynamicProp,
+ setDynamicProps,
+} from './dom/prop'
+export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
+export { setRef } from './dom/templateRef'
+
+export { defineComponent } from './apiDefineComponent'
+export {
+ type InjectionKey,
+ inject,
+ provide,
+ hasInjectionContext,
+} from './apiInject'
+export {
+ onBeforeMount,
+ onMounted,
+ onBeforeUpdate,
+ onUpdated,
+ onBeforeUnmount,
+ onUnmounted,
+ // onActivated,
+ // onDeactivated,
+ onRenderTracked,
+ onRenderTriggered,
+ onErrorCaptured,
+ // onServerPrefetch,
+} from './apiLifecycle'
+export { useAttrs, useSlots } from './apiSetupHelpers'
+export {
+ createVaporApp,
+ type App,
+ type AppConfig,
+ type AppContext,
+ type Plugin,
+ type ObjectPlugin,
+ type FunctionPlugin,
+} from './apiCreateVaporApp'
+export { createIf } from './apiCreateIf'
+export { createFor, createForSlots } from './apiCreateFor'
+export { createComponent } from './apiCreateComponent'
+
+export { resolveComponent, resolveDirective } from './helpers/resolveAssets'
+export { toHandlers } from './helpers/toHandlers'
+
+export { withDestructure } from './destructure'
+
+// **Internal** DOM-only runtime directive helpers
+export {
+ vModelText,
+ vModelCheckbox,
+ vModelRadio,
+ vModelSelect,
+ vModelDynamic,
+} from './directives/vModel'
+export { vShow } from './directives/vShow'
+
+// For devtools
+import {
+ type DevtoolsHook,
+ devtools as _devtools,
+ setDevtoolsHook as _setDevtoolsHook,
+} from './devtools'
+
+export const devtools = (
+ __DEV__ || __ESM_BUNDLER__ ? _devtools : undefined
+) as DevtoolsHook
+export const setDevtoolsHook = (
+ __DEV__ || __ESM_BUNDLER__ ? _setDevtoolsHook : NOOP
+) as typeof _setDevtoolsHook
--- /dev/null
- import {
- EffectFlags,
- ReactiveEffect,
- type SchedulerJob,
- SchedulerJobFlags,
- getCurrentScope,
- } from '@vue/reactivity'
++import { EffectFlags, ReactiveEffect, getCurrentScope } from '@vue/reactivity'
+import { invokeArrayFns } from '@vue/shared'
+import {
+ type ComponentInternalInstance,
+ getCurrentInstance,
+ setCurrentInstance,
+} from './component'
- import { queueJob, queuePostFlushCb } from './scheduler'
++import {
++ type SchedulerJob,
++ VaporSchedulerJobFlags,
++ queueJob,
++ queuePostFlushCb,
++} from './scheduler'
+import { VaporErrorCodes, callWithAsyncErrorHandling } from './errorHandling'
+import { invokeDirectiveHook } from './directives'
+
+export function renderEffect(cb: () => void): void {
+ const instance = getCurrentInstance()
+ const scope = getCurrentScope()
+
+ if (scope) {
+ const baseCb = cb
+ cb = () => scope.run(baseCb)
+ }
+
+ if (instance) {
+ const baseCb = cb
+ cb = () => {
+ const reset = setCurrentInstance(instance)
+ baseCb()
+ reset()
+ }
+ job.id = instance.uid
+ }
+
+ const effect = new ReactiveEffect(() =>
+ callWithAsyncErrorHandling(cb, instance, VaporErrorCodes.RENDER_FUNCTION),
+ )
+
+ effect.scheduler = () => queueJob(job)
+ if (__DEV__ && instance) {
+ effect.onTrack = instance.rtc
+ ? e => invokeArrayFns(instance.rtc!, e)
+ : void 0
+ effect.onTrigger = instance.rtg
+ ? e => invokeArrayFns(instance.rtg!, e)
+ : void 0
+ }
+ effect.run()
+
+ function job() {
+ if (!(effect.flags & EffectFlags.ACTIVE) || !effect.dirty) {
+ return
+ }
+
+ const reset = instance && setCurrentInstance(instance)
+
+ if (instance && instance.isMounted && !instance.isUpdating) {
+ instance.isUpdating = true
+
+ const { bu, u, scope } = instance
+ const { dirs } = scope
+ // beforeUpdate hook
+ if (bu) {
+ invokeArrayFns(bu)
+ }
+ if (dirs) {
+ invokeDirectiveHook(instance, 'beforeUpdate', scope)
+ }
+
+ effect.run()
+
+ queuePostFlushCb(() => {
+ instance.isUpdating = false
+ const reset = setCurrentInstance(instance)
+ if (dirs) {
+ invokeDirectiveHook(instance, 'updated', scope)
+ }
+ // updated hook
+ if (u) {
+ queuePostFlushCb(u)
+ }
+ reset()
+ })
+ } else {
+ effect.run()
+ }
+
+ reset && reset()
+ }
+}
+
+export function firstEffect(
+ instance: ComponentInternalInstance,
+ fn: () => void,
+): void {
+ const effect = new ReactiveEffect(fn)
+ const job: SchedulerJob = () => effect.run()
- job.flags! |= SchedulerJobFlags.PRE
++ job.flags! |= VaporSchedulerJobFlags.PRE
+ job.id = instance.uid
+ effect.scheduler = () => queueJob(job)
+ effect.run()
+}
--- /dev/null
- import {
- EffectFlags,
- type SchedulerJob,
- SchedulerJobFlags,
- type WatchScheduler,
- } from '@vue/reactivity'
++import type { WatchScheduler } from '@vue/reactivity'
+import type { ComponentInternalInstance } from './component'
+import { isArray } from '@vue/shared'
+
++export enum VaporSchedulerJobFlags {
++ QUEUED = 1 << 0,
++ PRE = 1 << 1,
++ /**
++ * Indicates whether the effect is allowed to recursively trigger itself
++ * when managed by the scheduler.
++ *
++ * By default, a job cannot trigger itself because some built-in method calls,
++ * e.g. Array.prototype.push actually performs reads as well (#1740) which
++ * can lead to confusing infinite loops.
++ * The allowed cases are component update functions and watch callbacks.
++ * Component update functions may update child component props, which in turn
++ * trigger flush: "pre" watch callbacks that mutates state that the parent
++ * relies on (#1801). Watch callbacks doesn't track its dependencies so if it
++ * triggers itself again, it's likely intentional and it is the user's
++ * responsibility to perform recursive state mutation that eventually
++ * stabilizes (#1727).
++ */
++ ALLOW_RECURSE = 1 << 2,
++ DISPOSED = 1 << 3,
++}
++
++export interface SchedulerJob extends Function {
++ id?: number
++ /**
++ * flags can technically be undefined, but it can still be used in bitwise
++ * operations just like 0.
++ */
++ flags?: VaporSchedulerJobFlags
++ /**
++ * Attached by renderer.ts when setting up a component's render effect
++ * Used to obtain component information when reporting max recursive updates.
++ */
++ i?: ComponentInternalInstance
++}
++
+export type SchedulerJobs = SchedulerJob | SchedulerJob[]
+export type QueueEffect = (
+ cb: SchedulerJobs,
+ suspense: ComponentInternalInstance | null,
+) => void
+
+let isFlushing = false
+let isFlushPending = false
+
+// TODO: The queues in Vapor need to be merged with the queues in Core.
+// this is a temporary solution, the ultimate goal is to support
+// the mixed use of vapor components and default components.
+const queue: SchedulerJob[] = []
+let flushIndex = 0
+
+// TODO: The queues in Vapor need to be merged with the queues in Core.
+// this is a temporary solution, the ultimate goal is to support
+// the mixed use of vapor components and default components.
+const pendingPostFlushCbs: SchedulerJob[] = []
+let activePostFlushCbs: SchedulerJob[] | null = null
+let postFlushIndex = 0
+
+const resolvedPromise = /*#__PURE__*/ Promise.resolve() as Promise<any>
+let currentFlushPromise: Promise<void> | null = null
+
+export function queueJob(job: SchedulerJob): void {
+ let lastOne: SchedulerJob | undefined
- if (!(job.flags! & SchedulerJobFlags.QUEUED)) {
++ if (!(job.flags! & VaporSchedulerJobFlags.QUEUED)) {
+ if (job.id == null) {
+ queue.push(job)
+ } else if (
+ // fast path when the job id is larger than the tail
- !(job.flags! & SchedulerJobFlags.PRE) &&
++ !(job.flags! & VaporSchedulerJobFlags.PRE) &&
+ job.id >= (((lastOne = queue[queue.length - 1]) && lastOne.id) || 0)
+ ) {
+ queue.push(job)
+ } else {
+ queue.splice(findInsertionIndex(job.id), 0, job)
+ }
+
- if (!(job.flags! & SchedulerJobFlags.ALLOW_RECURSE)) {
- job.flags! |= SchedulerJobFlags.QUEUED
++ if (!(job.flags! & VaporSchedulerJobFlags.ALLOW_RECURSE)) {
++ job.flags! |= VaporSchedulerJobFlags.QUEUED
+ }
+ queueFlush()
+ }
+}
+
+export function queuePostFlushCb(cb: SchedulerJobs): void {
+ if (!isArray(cb)) {
- if (!(cb.flags! & SchedulerJobFlags.QUEUED)) {
++ if (!(cb.flags! & VaporSchedulerJobFlags.QUEUED)) {
+ pendingPostFlushCbs.push(cb)
- if (!(cb.flags! & SchedulerJobFlags.ALLOW_RECURSE)) {
- cb.flags! |= SchedulerJobFlags.QUEUED
++ if (!(cb.flags! & VaporSchedulerJobFlags.ALLOW_RECURSE)) {
++ cb.flags! |= VaporSchedulerJobFlags.QUEUED
+ }
+ }
+ } else {
+ // if cb is an array, it is a component lifecycle hook which can only be
+ // triggered by a job, which is already deduped in the main queue, so
+ // we can skip duplicate check here to improve perf
+ pendingPostFlushCbs.push(...cb)
+ }
+ queueFlush()
+}
+
+function queueFlush() {
+ if (!isFlushing && !isFlushPending) {
+ isFlushPending = true
+ currentFlushPromise = resolvedPromise.then(flushJobs)
+ }
+}
+
+export function flushPostFlushCbs(): void {
+ if (!pendingPostFlushCbs.length) return
+
+ const deduped = [...new Set(pendingPostFlushCbs)]
+ pendingPostFlushCbs.length = 0
+
+ // #1947 already has active queue, nested flushPostFlushCbs call
+ if (activePostFlushCbs) {
+ activePostFlushCbs.push(...deduped)
+ return
+ }
+
+ activePostFlushCbs = deduped
+
+ activePostFlushCbs.sort((a, b) => getId(a) - getId(b))
+
+ for (
+ postFlushIndex = 0;
+ postFlushIndex < activePostFlushCbs.length;
+ postFlushIndex++
+ ) {
+ activePostFlushCbs[postFlushIndex]()
- activePostFlushCbs[postFlushIndex].flags! &= ~SchedulerJobFlags.QUEUED
++ activePostFlushCbs[postFlushIndex].flags! &= ~VaporSchedulerJobFlags.QUEUED
+ }
+ activePostFlushCbs = null
+ postFlushIndex = 0
+}
+
+// TODO: dev mode and checkRecursiveUpdates
+function flushJobs() {
+ isFlushPending = false
+ isFlushing = true
+
+ // Sort queue before flush.
+ // This ensures that:
+ // 1. Components are updated from parent to child. (because parent is always
+ // created before the child so its render effect will have smaller
+ // priority number)
+ // 2. If a component is unmounted during a parent component's update,
+ // its update can be skipped.
+ queue.sort(comparator)
+
+ try {
+ for (let i = 0; i < queue!.length; i++) {
+ queue[i]()
- queue[i].flags! &= ~SchedulerJobFlags.QUEUED
++ queue[i].flags! &= ~VaporSchedulerJobFlags.QUEUED
+ }
+ } finally {
+ flushIndex = 0
+ queue.length = 0
+
+ flushPostFlushCbs()
+
+ isFlushing = false
+ currentFlushPromise = null
+ // some postFlushCb queued jobs!
+ // keep flushing until it drains.
+ if (queue.length || pendingPostFlushCbs.length) {
+ flushJobs()
+ }
+ }
+}
+
+export function nextTick<T = void, R = void>(
+ this: T,
+ fn?: (this: T) => R,
+): Promise<Awaited<R>> {
+ const p = currentFlushPromise || resolvedPromise
+ return fn ? p.then(this ? fn.bind(this) : fn) : p
+}
+
+// #2768
+// Use binary-search to find a suitable position in the queue,
+// so that the queue maintains the increasing order of job's id,
+// which can prevent the job from being skipped and also can avoid repeated patching.
+function findInsertionIndex(id: number) {
+ // the start index should be `flushIndex + 1`
+ let start = flushIndex + 1
+ let end = queue.length
+
+ while (start < end) {
+ const middle = (start + end) >>> 1
+ const middleJob = queue[middle]
+ const middleJobId = getId(middleJob)
+ if (
+ middleJobId < id ||
- (middleJobId === id && middleJob.flags! & SchedulerJobFlags.PRE)
++ (middleJobId === id && middleJob.flags! & VaporSchedulerJobFlags.PRE)
+ ) {
+ start = middle + 1
+ } else {
+ end = middle
+ }
+ }
+
+ return start
+}
+
+const getId = (job: SchedulerJob): number =>
+ job.id == null ? Infinity : job.id
+
+const comparator = (a: SchedulerJob, b: SchedulerJob): number => {
+ const diff = getId(a) - getId(b)
+ if (diff === 0) {
- const isAPre = a.flags! & SchedulerJobFlags.PRE
- const isBPre = b.flags! & SchedulerJobFlags.PRE
++ const isAPre = a.flags! & VaporSchedulerJobFlags.PRE
++ const isBPre = b.flags! & VaporSchedulerJobFlags.PRE
+ if (isAPre && !isBPre) return -1
+ if (isBPre && !isAPre) return 1
+ }
+ return diff
+}
+
+export type SchedulerFactory = (
+ instance: ComponentInternalInstance | null,
+) => WatchScheduler
-
- export const createVaporSyncScheduler: SchedulerFactory =
- instance => (job, effect, immediateFirstRun, hasCb) => {
- if (immediateFirstRun) {
- effect.flags |= EffectFlags.NO_BATCH
- if (!hasCb) effect.run()
- } else {
- job()
- }
- }
-
- export const createVaporPreScheduler: SchedulerFactory =
- instance => (job, effect, immediateFirstRun, hasCb) => {
- if (!immediateFirstRun) {
- job.flags! |= SchedulerJobFlags.PRE
- if (instance) job.id = instance.uid
- queueJob(job)
- } else if (!hasCb) {
- effect.run()
- }
- }
-
- export const createVaporPostScheduler: SchedulerFactory =
- instance => (job, effect, immediateFirstRun, hasCb) => {
- if (!immediateFirstRun) {
- queuePostFlushCb(job)
- } else if (!hasCb) {
- queuePostFlushCb(effect.run.bind(effect))
- }
- }
'onVnodeBeforeUnmount,onVnodeUnmounted',
)
+export const isBuiltInTag: (key: string) => boolean =
+ /*#__PURE__*/ makeMap('slot,component')
+
export const isBuiltInDirective: (key: string) => boolean =
- /*#__PURE__*/ makeMap(
+ /*@__PURE__*/ makeMap(
'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo',
)
--- /dev/null
- export const E2E_TIMEOUT = 30 * 1000
+import puppeteer, {
+ type Browser,
+ type ClickOptions,
+ type Page,
+ type PuppeteerLaunchOptions,
+} from 'puppeteer'
+
- export const timeout = (n: number) => new Promise(r => setTimeout(r, n))
++export const E2E_TIMEOUT: number = 30 * 1000
+
+const puppeteerOptions: PuppeteerLaunchOptions = {
+ args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [],
+ headless: true,
+}
+
+const maxTries = 30
- ) {
++export const timeout = (n: number): Promise<any> =>
++ new Promise(r => setTimeout(r, n))
+
+export async function expectByPolling(
+ poll: () => Promise<any>,
+ expected: string,
- export function setupPuppeteer() {
++): Promise<void> {
+ for (let tries = 0; tries < maxTries; tries++) {
+ const actual = (await poll()) || ''
+ if (actual.indexOf(expected) > -1 || tries === maxTries - 1) {
+ expect(actual).toMatch(expected)
+ break
+ } else {
+ await timeout(50)
+ }
+ }
+}
+
- browser = await puppeteer.launch(puppeteerOptions)
++interface PuppeteerUtils {
++ page: () => Page
++ click(selector: string, options?: ClickOptions): Promise<void>
++ count(selector: string): Promise<number>
++ text(selector: string): Promise<string | null>
++ value(selector: string): Promise<string>
++ html(selector: string): Promise<string>
++ classList(selector: string): Promise<string[]>
++ children(selector: string): Promise<any[]>
++ isVisible(selector: string): Promise<boolean>
++ isChecked(selector: string): Promise<boolean>
++ isFocused(selector: string): Promise<boolean>
++ setValue(selector: string, value: string): Promise<any>
++ typeValue(selector: string, value: string): Promise<any>
++ enterValue(selector: string, value: string): Promise<any>
++ clearValue(selector: string): Promise<any>
++ timeout(time: number): Promise<any>
++ nextFrame(): Promise<any>
++}
++
++export function setupPuppeteer(args?: string[]): PuppeteerUtils {
+ let browser: Browser
+ let page: Page
+
++ const resolvedOptions = args
++ ? {
++ ...puppeteerOptions,
++ args: [...puppeteerOptions.args!, ...args],
++ }
++ : puppeteerOptions
++
+ beforeAll(async () => {
- console.error(
- `Error from Puppeteer-loaded page:\n`,
- err.remoteObject().description,
- )
++ browser = await puppeteer.launch(resolvedOptions)
+ }, 20000)
+
+ beforeEach(async () => {
+ page = await browser.newPage()
+
+ await page.evaluateOnNewDocument(() => {
+ localStorage.clear()
+ })
+
+ page.on('console', e => {
+ if (e.type() === 'error') {
+ const err = e.args()[0]
- async function click(selector: string, options?: ClickOptions) {
++ console.error(`Error from Puppeteer-loaded page:\n`, err.remoteObject())
+ }
+ })
+ })
+
+ afterEach(async () => {
+ await page.close()
+ })
+
+ afterAll(async () => {
+ await browser.close()
+ })
+
- async function count(selector: string) {
++ async function click(
++ selector: string,
++ options?: ClickOptions,
++ ): Promise<void> {
+ await page.click(selector, options)
+ }
+
- async function text(selector: string) {
- return await page.$eval(selector, node => node.textContent)
++ async function count(selector: string): Promise<number> {
+ return (await page.$$(selector)).length
+ }
+
- async function value(selector: string) {
- return await page.$eval(selector, node => (node as HTMLInputElement).value)
++ async function text(selector: string): Promise<string | null> {
++ return page.$eval(selector, node => node.textContent)
+ }
+
- async function html(selector: string) {
- return await page.$eval(selector, node => node.innerHTML)
++ async function value(selector: string): Promise<string> {
++ return page.$eval(selector, node => (node as HTMLInputElement).value)
+ }
+
- async function classList(selector: string) {
- return await page.$eval(selector, (node: any) => [...node.classList])
++ async function html(selector: string): Promise<string> {
++ return page.$eval(selector, node => node.innerHTML)
+ }
+
- async function children(selector: string) {
- return await page.$eval(selector, (node: any) => [...node.children])
++ async function classList(selector: string): Promise<string[]> {
++ return page.$eval(selector, (node: any) => [...node.classList])
+ }
+
- async function isVisible(selector: string) {
++ async function children(selector: string): Promise<any[]> {
++ return page.$eval(selector, (node: any) => [...node.children])
+ }
+
++ async function isVisible(selector: string): Promise<boolean> {
+ const display = await page.$eval(selector, node => {
+ return window.getComputedStyle(node).display
+ })
+ return display !== 'none'
+ }
+
+ async function isChecked(selector: string) {
+ return await page.$eval(
+ selector,
+ node => (node as HTMLInputElement).checked,
+ )
+ }
+
+ async function isFocused(selector: string) {
+ return await page.$eval(selector, node => node === document.activeElement)
+ }
+
+ async function setValue(selector: string, value: string) {
+ await page.$eval(
+ selector,
+ (node, value) => {
+ ;(node as HTMLInputElement).value = value as string
+ node.dispatchEvent(new Event('input'))
+ },
+ value,
+ )
+ }
+
+ async function typeValue(selector: string, value: string) {
+ const el = (await page.$(selector))!
+ await el.evaluate(node => ((node as HTMLInputElement).value = ''))
+ await el.type(value)
+ }
+
+ async function enterValue(selector: string, value: string) {
+ const el = (await page.$(selector))!
+ await el.evaluate(node => ((node as HTMLInputElement).value = ''))
+ await el.type(value)
+ await el.press('Enter')
+ }
+
+ async function clearValue(selector: string) {
+ return await page.$eval(
+ selector,
+ node => ((node as HTMLInputElement).value = ''),
+ )
+ }
+
+ function timeout(time: number) {
+ return page.evaluate(time => {
+ return new Promise(r => {
+ setTimeout(r, time)
+ })
+ }, time)
+ }
+
+ function nextFrame() {
+ return page.evaluate(() => {
+ return new Promise(resolve => {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(resolve)
+ })
+ })
+ })
+ }
+
+ return {
+ page: () => page,
+ click,
+ count,
+ text,
+ value,
+ html,
+ classList,
+ children,
+ isVisible,
+ isChecked,
+ isFocused,
+ setValue,
+ typeValue,
+ enterValue,
+ clearValue,
+ timeout,
+ nextFrame,
+ }
+}
--- /dev/null
++/// <reference types="vite/client" />
++
+import { createVaporApp } from 'vue/vapor'
+import { createApp } from 'vue'
+import './style.css'
+
+const modules = import.meta.glob<any>('./**/*.(vue|js)')
+const mod = (modules['.' + location.pathname] || modules['./App.vue'])()
+
+mod.then(({ default: mod }) => {
+ const app = (mod.vapor ? createVaporApp : createApp)(mod)
+ app.mount('#app')
+
+ // @ts-expect-error
+ globalThis.unmount = () => {
+ app.unmount()
+ }
+})
--- /dev/null
--- /dev/null
++{
++ "extends": "../tsconfig.json",
++ "compilerOptions": {
++ "isolatedDeclarations": false,
++ "allowJs": true
++ },
++ "include": ["**/*"]
++}
version: 0.30.11
source-map-js:
specifier: ^1.2.0
-- version: 1.2.0
++ version: 1.2.1
vite:
specifier: ^5.4.0
version: 5.4.0
'@types/serve-handler':
specifier: ^6.1.4
version: 6.1.4
- '@vitest/coverage-istanbul':
- specifier: ^1.6.0
- version: 1.6.0(vitest@1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6))
+ '@vitest/coverage-v8':
+ specifier: ^2.1.1
- version: 2.1.1(vitest@2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0))
++ version: 2.1.1(vitest@2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6))
+ '@vitest/ui':
- specifier: ^1.6.0
- version: 1.6.0(vitest@1.6.0)
++ specifier: ^2.1.1
++ version: 2.1.1(vitest@2.1.1)
'@vue/consolidate':
specifier: 1.0.0
version: 1.0.0
specifier: ^2.4.1
version: 2.4.1
esbuild:
- specifier: ^0.23.0
- version: 0.23.0
+ specifier: ^0.23.1
+ version: 0.23.1
esbuild-plugin-polyfill-node:
specifier: ^0.3.0
- version: 0.3.0(esbuild@0.23.0)
+ version: 0.3.0(esbuild@0.23.1)
eslint:
- specifier: ^9.8.0
- version: 9.8.0
+ specifier: ^9.10.0
+ version: 9.10.0
eslint-plugin-import-x:
- specifier: ^3.1.0
- version: 3.1.0(eslint@9.8.0)(typescript@5.5.4)
+ specifier: ^4.2.1
+ version: 4.2.1(eslint@9.10.0)(typescript@5.6.2)
eslint-plugin-vitest:
specifier: ^0.5.4
- version: 0.5.4(eslint@9.8.0)(typescript@5.5.4)(vitest@1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6))
- version: 0.5.4(eslint@9.10.0)(typescript@5.6.2)(vitest@2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0))
++ version: 0.5.4(eslint@9.10.0)(typescript@5.6.2)(vitest@2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6))
estree-walker:
specifier: 'catalog:'
version: 2.0.2
specifier: ^2.4.3
version: 2.4.3
tslib:
- specifier: ^2.6.3
- version: 2.6.3
- tsx:
- specifier: ^4.16.5
- version: 4.17.0
+ specifier: ^2.7.0
+ version: 2.7.0
typescript:
- specifier: ~5.5.4
- version: 5.5.4
+ specifier: ~5.6.2
+ version: 5.6.2
typescript-eslint:
- specifier: ^8.0.0
- version: 8.0.1(eslint@9.8.0)(typescript@5.5.4)
+ specifier: ^8.5.0
+ version: 8.5.0(eslint@9.10.0)(typescript@5.6.2)
vite:
specifier: 'catalog:'
- version: 5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
- version: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
++ version: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
vitest:
- specifier: ^1.6.0
- version: 1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6)
+ specifier: ^2.1.1
- version: 2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0)
++ version: 2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6)
+
+ benchmark:
+ dependencies:
+ '@vitejs/plugin-vue':
+ specifier: npm:@vue-vapor/vite-plugin-vue@0.0.0-alpha.6
- version: '@vue-vapor/vite-plugin-vue@0.0.0-alpha.6(vite@5.3.3(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))(vue@3.5.0-beta.1(typescript@5.5.4))'
++ version: '@vue-vapor/vite-plugin-vue@0.0.0-alpha.6(vite@5.3.3(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@3.5.6(typescript@5.6.2))'
+ connect:
+ specifier: ^3.7.0
+ version: 3.7.0
+ sirv:
+ specifier: ^2.0.4
+ version: 2.0.4
+ vite:
+ specifier: ^5.0.12
- version: 5.3.3(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
++ version: 5.3.3(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ devDependencies:
+ '@types/connect':
+ specifier: ^3.4.38
+ version: 3.4.38
+ terser:
+ specifier: ^5.31.6
+ version: 5.31.6
- version: 5.1.2(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0))(vue@packages+vue)
+ packages-private/dts-built-test:
+ dependencies:
+ '@vue/reactivity':
+ specifier: workspace:*
+ version: link:../../packages/reactivity
+ '@vue/shared':
+ specifier: workspace:*
+ version: link:../../packages/shared
+ vue:
+ specifier: workspace:*
+ version: link:../../packages/vue
+
+ packages-private/dts-test:
+ dependencies:
+ dts-built-test:
+ specifier: workspace:*
+ version: link:../dts-built-test
+ vue:
+ specifier: workspace:*
+ version: link:../../packages/vue
+
+ packages-private/sfc-playground:
+ dependencies:
+ '@vue/repl':
+ specifier: ^4.4.2
+ version: 4.4.2
+ file-saver:
+ specifier: ^2.0.5
+ version: 2.0.5
+ jszip:
+ specifier: ^3.10.1
+ version: 3.10.1
+ vue:
+ specifier: workspace:*
+ version: link:../../packages/vue
+ devDependencies:
+ '@vitejs/plugin-vue':
+ specifier: 'catalog:'
- version: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
++ version: 5.1.2(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@packages+vue)
+ vite:
+ specifier: 'catalog:'
- version: 5.1.2(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0))(vue@packages+vue)
++ version: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+
+ packages-private/template-explorer:
+ dependencies:
++ '@vue/compiler-vapor':
++ specifier: workspace:^
++ version: link:../../packages/compiler-vapor
+ monaco-editor:
+ specifier: ^0.51.0
+ version: 0.51.0
+ source-map-js:
+ specifier: ^1.2.1
+ version: 1.2.1
+
+ packages-private/vite-debug:
+ devDependencies:
+ '@vitejs/plugin-vue':
+ specifier: 'catalog:'
- version: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
++ version: 5.1.2(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@packages+vue)
+ vite:
+ specifier: 'catalog:'
++ version: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ vue:
+ specifier: workspace:*
+ version: link:../../packages/vue
+
packages/compiler-core:
dependencies:
'@babel/parser':
version: 2.0.2
source-map-js:
specifier: 'catalog:'
-- version: 1.2.0
++ version: 1.2.1
devDependencies:
'@babel/types':
specifier: 'catalog:'
specifier: 'catalog:'
version: 0.30.11
postcss:
- specifier: ^8.4.40
- version: 8.4.41
+ specifier: ^8.4.47
+ version: 8.4.47
source-map-js:
specifier: 'catalog:'
-- version: 1.2.0
++ version: 1.2.1
devDependencies:
'@babel/types':
specifier: 'catalog:'
specifier: workspace:*
version: link:../shared
- packages/dts-built-test:
- dependencies:
- '@vue/reactivity':
- specifier: workspace:*
- version: link:../reactivity
- '@vue/shared':
- specifier: workspace:*
- version: link:../shared
- vue:
- specifier: workspace:*
- version: link:../vue
-
- packages/dts-test:
- dependencies:
- '@vue/dts-built-test':
- specifier: workspace:*
- version: link:../dts-built-test
- vue:
- specifier: workspace:*
- version: link:../vue
-
+ packages/compiler-vapor:
+ dependencies:
+ '@vue/compiler-dom':
+ specifier: workspace:*
+ version: link:../compiler-dom
+ '@vue/shared':
+ specifier: workspace:*
+ version: link:../shared
+ source-map-js:
+ specifier: ^1.0.2
+ version: 1.2.0
+
packages/reactivity:
dependencies:
'@vue/shared':
version: 2.0.2
source-map-js:
specifier: 'catalog:'
-- version: 1.2.0
++ version: 1.2.1
vue:
specifier: workspace:*
version: link:../vue
- version: '@vue-vapor/vite-plugin-vue@0.0.0-alpha.4(vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))(vue@packages+vue)'
+ packages/vue-vapor:
+ dependencies:
+ '@vue/compiler-vapor':
+ specifier: workspace:*
+ version: link:../compiler-vapor
+ '@vue/runtime-vapor':
+ specifier: workspace:*
+ version: link:../runtime-vapor
+
+ playground:
+ dependencies:
+ '@vueuse/core':
+ specifier: ^10.7.2
+ version: 10.9.0(vue@packages+vue)
+ vue:
+ specifier: workspace:*
+ version: link:../packages/vue
+ devDependencies:
+ '@vitejs/plugin-vue':
+ specifier: npm:@vue-vapor/vite-plugin-vue@0.0.0-alpha.4
- version: 5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
++ version: '@vue-vapor/vite-plugin-vue@0.0.0-alpha.4(vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@packages+vue)'
+ vite:
+ specifier: ^5.0.12
- version: 0.2.1(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)(vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))
++ version: 5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ vite-hyper-config:
+ specifier: ^0.2.1
- version: 0.7.42(rollup@4.20.0)(vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))
++ version: 0.2.1(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)(vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))
+ vite-plugin-inspect:
+ specifier: ^0.7.42
++ version: 0.7.42(rollup@4.21.3)(vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))
+
packages:
'@ampproject/remapping@2.3.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@puppeteer/browsers@2.3.0':
- resolution: {integrity: sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==}
+ '@polka/url@1.0.0-next.25':
+ resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
+
+ '@puppeteer/browsers@2.4.0':
+ resolution: {integrity: sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g==}
engines: {node: '>=18'}
hasBin: true
resolution: {integrity: sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==}
cpu: [arm]
os: [linux]
- libc: [glibc]
- libc: [glibc]
+ '@rollup/rollup-linux-arm-gnueabihf@4.21.3':
+ resolution: {integrity: sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==}
+ cpu: [arm]
+ os: [linux]
+
'@rollup/rollup-linux-arm-musleabihf@4.20.0':
resolution: {integrity: sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==}
cpu: [arm]
os: [linux]
- libc: [musl]
- libc: [musl]
+ '@rollup/rollup-linux-arm-musleabihf@4.21.3':
+ resolution: {integrity: sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==}
+ cpu: [arm]
+ os: [linux]
+
'@rollup/rollup-linux-arm64-gnu@4.20.0':
resolution: {integrity: sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
- libc: [glibc]
+ '@rollup/rollup-linux-arm64-gnu@4.21.3':
+ resolution: {integrity: sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==}
+ cpu: [arm64]
+ os: [linux]
+
'@rollup/rollup-linux-arm64-musl@4.20.0':
resolution: {integrity: sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==}
cpu: [arm64]
os: [linux]
- libc: [musl]
- libc: [musl]
+ '@rollup/rollup-linux-arm64-musl@4.21.3':
+ resolution: {integrity: sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==}
+ cpu: [arm64]
+ os: [linux]
+
'@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
resolution: {integrity: sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
- libc: [glibc]
+ '@rollup/rollup-linux-powerpc64le-gnu@4.21.3':
+ resolution: {integrity: sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==}
+ cpu: [ppc64]
+ os: [linux]
+
'@rollup/rollup-linux-riscv64-gnu@4.20.0':
resolution: {integrity: sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
- libc: [glibc]
+ '@rollup/rollup-linux-riscv64-gnu@4.21.3':
+ resolution: {integrity: sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==}
+ cpu: [riscv64]
+ os: [linux]
+
'@rollup/rollup-linux-s390x-gnu@4.20.0':
resolution: {integrity: sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
- libc: [glibc]
+ '@rollup/rollup-linux-s390x-gnu@4.21.3':
+ resolution: {integrity: sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==}
+ cpu: [s390x]
+ os: [linux]
+
'@rollup/rollup-linux-x64-gnu@4.20.0':
resolution: {integrity: sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==}
cpu: [x64]
os: [linux]
- libc: [glibc]
- libc: [glibc]
+ '@rollup/rollup-linux-x64-gnu@4.21.3':
+ resolution: {integrity: sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==}
+ cpu: [x64]
+ os: [linux]
+
'@rollup/rollup-linux-x64-musl@4.20.0':
resolution: {integrity: sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==}
cpu: [x64]
os: [linux]
- libc: [musl]
- libc: [musl]
+ '@rollup/rollup-linux-x64-musl@4.21.3':
+ resolution: {integrity: sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==}
+ cpu: [x64]
+ os: [linux]
+
'@rollup/rollup-win32-arm64-msvc@4.20.0':
resolution: {integrity: sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==}
cpu: [arm64]
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
- '@swc/core-linux-arm64-musl@1.7.6':
- resolution: {integrity: sha512-QI8QGL0HGT42tj7F1A+YAzhGkJjUcvvTfI1e2m704W0Enl2/UIK9v5D1zvQzYwusRyKuaQfbeBRYDh0NcLOGLg==}
+ '@swc/core-linux-arm64-musl@1.7.26':
+ resolution: {integrity: sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
- libc: [musl]
- '@swc/core-linux-x64-gnu@1.7.6':
- resolution: {integrity: sha512-61AYVzhjuNQAVIKKWOJu3H0/pFD28RYJGxnGg3YMhvRLRyuWNyY5Nyyj2WkKcz/ON+g38Arlz00NT1LDIViRLg==}
+ '@swc/core-linux-x64-gnu@1.7.26':
+ resolution: {integrity: sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
- libc: [glibc]
- '@swc/core-linux-x64-musl@1.7.6':
- resolution: {integrity: sha512-hQFznpfLK8XajfAAN9Cjs0w/aVmO7iu9VZvInyrTCRcPqxV5O+rvrhRxKvC1LRMZXr5M6JRSRtepp5w+TK4kAw==}
+ '@swc/core-linux-x64-musl@1.7.26':
+ resolution: {integrity: sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
- libc: [musl]
- '@swc/core-win32-arm64-msvc@1.7.6':
- resolution: {integrity: sha512-Aqsd9afykVMuekzjm4X4TDqwxmG4CrzoOSFe0hZrn9SMio72l5eAPnMtYoe5LsIqtjV8MNprLfXaNbjHjTegmA==}
+ '@swc/core-win32-arm64-msvc@1.7.26':
+ resolution: {integrity: sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
vite: ^5.0.0
vue: ^3.2.25
- '@vitest/coverage-istanbul@1.6.0':
- resolution: {integrity: sha512-h/BwpXehkkS0qsNCS00QxiupAqVkNi0WT19BR0dQvlge5oHghoSVLx63fABYFoKxVb7Ue7+k6V2KokmQ1zdMpg==}
+ '@vitest/coverage-v8@2.1.1':
+ resolution: {integrity: sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==}
peerDependencies:
- vitest: 1.6.0
+ '@vitest/browser': 2.1.1
+ vitest: 2.1.1
+ peerDependenciesMeta:
+ '@vitest/browser':
+ optional: true
- '@vitest/expect@1.6.0':
- resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
+ '@vitest/expect@2.1.1':
+ resolution: {integrity: sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==}
- '@vitest/runner@1.6.0':
- resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==}
+ '@vitest/mocker@2.1.1':
+ resolution: {integrity: sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==}
+ peerDependencies:
+ '@vitest/spy': 2.1.1
+ msw: ^2.3.5
+ vite: ^5.0.0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@2.1.1':
+ resolution: {integrity: sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==}
- '@vitest/snapshot@1.6.0':
- resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==}
+ '@vitest/runner@2.1.1':
+ resolution: {integrity: sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==}
- '@vitest/spy@1.6.0':
- resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==}
+ '@vitest/snapshot@2.1.1':
+ resolution: {integrity: sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==}
- '@vitest/ui@1.6.0':
- resolution: {integrity: sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==}
+ '@vitest/spy@2.1.1':
+ resolution: {integrity: sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==}
+
++ '@vitest/ui@2.1.1':
++ resolution: {integrity: sha512-IIxo2LkQDA+1TZdPLYPclzsXukBWd5dX2CKpGqH8CCt8Wh0ZuDn4+vuQ9qlppEju6/igDGzjWF/zyorfsf+nHg==}
+ peerDependencies:
- vitest: 1.6.0
++ vitest: 2.1.1
+
- '@vitest/utils@1.6.0':
- resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
+ '@vitest/utils@2.1.1':
+ resolution: {integrity: sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==}
- '@vue/compiler-core@3.5.0-beta.1':
- resolution: {integrity: sha512-MLP2yH21NFnVn+WhUsrRFR+wwXuBWHQ4YmXou1zVaXSfwqwGonf0KC7FBbXz3RbqPH0v2yksWpZFJYnTY++yNQ==}
+ '@vue-vapor/vite-plugin-vue@0.0.0-alpha.4':
+ resolution: {integrity: sha512-18LGTnk07uKIWZtYjpyH71PZWIMrwBwiVqjG8bCS5Q7ebISdTUP2N3Lx1vfQNSoGeBV8rxfekfu7XGXRTjJ9gQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ vite: ^5.0.0
+ vue: '*'
+
+ '@vue-vapor/vite-plugin-vue@0.0.0-alpha.6':
+ resolution: {integrity: sha512-V2aTQ7bkDXsoPvYIkTA54m3ypUXDIVpTFspn+ycuYcMfIY37cZ0ny6jm/afNY6k1DiaQ9JfAMBXAKzTBpu2B9A==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ vite: ^5.0.0
+ vue: '*'
+
- '@vue/compiler-dom@3.5.0-beta.1':
- resolution: {integrity: sha512-DAC/58eo5XlYdrUXRIf3eWDMbKWM1I85bQfIRIqt7vCE2a2yGmx2LIyI/BEio4uI1Sdf/g16kOzk3BDmFkr1GA==}
++ '@vue/compiler-core@3.5.6':
++ resolution: {integrity: sha512-r+gNu6K4lrvaQLQGmf+1gc41p3FO2OUJyWmNqaIITaJU6YFiV5PtQSFZt8jfztYyARwqhoCayjprC7KMvT3nRA==}
+
- '@vue/compiler-sfc@3.5.0-beta.1':
- resolution: {integrity: sha512-0139cGju9//Wpm90rtwDy6+/1s61Ba04Mn8+X1Xgo6D9xR3h7yLmgHU7OvG9Mh3LwtlB0sQIUeYZMvF995r4ww==}
++ '@vue/compiler-dom@3.5.6':
++ resolution: {integrity: sha512-xRXqxDrIqK8v8sSScpistyYH0qYqxakpsIvqMD2e5sV/PXQ1mTwtXp4k42yHK06KXxKSmitop9e45Ui/3BrTEw==}
+
- '@vue/compiler-ssr@3.5.0-beta.1':
- resolution: {integrity: sha512-aC58zZiLS//lqH6DdOPicv5crn8uSkBMilpGR1lKISViI09n5Gz0Ov0c35lYiVk9WifshTXU+BPQut3huKYySA==}
++ '@vue/compiler-sfc@3.5.6':
++ resolution: {integrity: sha512-pjWJ8Kj9TDHlbF5LywjVso+BIxCY5wVOLhkEXRhuCHDxPFIeX1zaFefKs8RYoHvkSMqRWt93a0f2gNJVJixHwg==}
+
++ '@vue/compiler-ssr@3.5.6':
++ resolution: {integrity: sha512-VpWbaZrEOCqnmqjE83xdwegtr5qO/2OPUC6veWgvNqTJ3bYysz6vY3VqMuOijubuUYPRpG3OOKIh9TD0Stxb9A==}
+
'@vue/consolidate@1.0.0':
resolution: {integrity: sha512-oTyUE+QHIzLw2PpV14GD/c7EohDyP64xCniWTcqcEmTd699eFqTIwOmtDYjcO1j3QgdXoJEoWv1/cCdLrRoOfg==}
engines: {node: '>= 0.12.0'}
- '@vue/reactivity@3.5.0-beta.1':
- resolution: {integrity: sha512-3dBZPdQxGcVCgeJv9KlGuK8a++PUj+OAJ8U89h+77SHMDAKXpLLjnpL+VfreAl37Z39ye4AJyfeYvaXV7fdlcA==}
++ '@vue/reactivity@3.5.6':
++ resolution: {integrity: sha512-shZ+KtBoHna5GyUxWfoFVBCVd7k56m6lGhk5e+J9AKjheHF6yob5eukssHRI+rzvHBiU1sWs/1ZhNbLExc5oYQ==}
+
- '@vue/repl@4.3.1':
- resolution: {integrity: sha512-yzUuLhR+MqOGBDES+xbnm27SfPIEv7XKwhFWWpQhL7HUbXj77GVu+x50Q56JhCWWKTUJzk9MOvAn7bSgdvB5og==}
+ '@vue/repl@4.4.2':
+ resolution: {integrity: sha512-MEAsBK/YzMFGINOBzqM40XTeIYAUsg7CqvXvD5zi0rhYEQrPfEUIdexmMjdm7kVKsKmcvIHxrFK2DFC35m9kHw==}
- '@vue/runtime-core@3.5.0-beta.1':
- resolution: {integrity: sha512-j+ivXaIRSZbJJGf9ZZpcf+4vqM3DC3AMgmoRrQ8DJExYIU6mvpkSNUfPRBw3QROoD7BjcuImRN6Ia2QxnlwDfw==}
++ '@vue/runtime-core@3.5.6':
++ resolution: {integrity: sha512-FpFULR6+c2lI+m1fIGONLDqPQO34jxV8g6A4wBOgne8eSRHP6PQL27+kWFIx5wNhhjkO7B4rgtsHAmWv7qKvbg==}
+
- '@vue/runtime-dom@3.5.0-beta.1':
- resolution: {integrity: sha512-16xac1YVuQtSsIQsY+94fHlg9QsQOxIZrr66kcHXYN9bSA8SqrTmA6JpfdwQfp+xQMVyRt+xb/K1c8plec9rxQ==}
++ '@vue/runtime-dom@3.5.6':
++ resolution: {integrity: sha512-SDPseWre45G38ENH2zXRAHL1dw/rr5qp91lS4lt/nHvMr0MhsbCbihGAWLXNB/6VfFOJe2O+RBRkXU+CJF7/sw==}
+
- '@vue/server-renderer@3.5.0-beta.1':
- resolution: {integrity: sha512-siDsHX84Yb9nF5H2Xp5h8mb/qXftNbgFiEN2Dr9N1RUaPXcz9Ai4grbMg6yTVm8aoC4gCXBgDVms+QRqSX3Xdg==}
++ '@vue/server-renderer@3.5.6':
++ resolution: {integrity: sha512-zivnxQnOnwEXVaT9CstJ64rZFXMS5ZkKxCjDQKiMSvUhXRzFLWZVbaBiNF4HGDqGNNsTgmjcCSmU6TB/0OOxLA==}
+ peerDependencies:
- vue: 3.5.0-beta.1
++ vue: 3.5.6
+
- '@vue/shared@3.5.0-beta.1':
- resolution: {integrity: sha512-RbjXOkVFA+92CWL8HLexUKIl3yUH0PGuzfjDtaNmr4WRP8vlA7xOyRm4iX+jl/KCbZb9JjC0r8yYWqNiMdeSJQ==}
++ '@vue/shared@3.5.6':
++ resolution: {integrity: sha512-eidH0HInnL39z6wAt6SFIwBrvGOpDWsDxlw3rCgo1B+CQ1781WzQUSU3YjxgdkcJo9Q8S6LmXTkvI+cLHGkQfA==}
+
+ '@vueuse/core@10.9.0':
+ resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==}
+
+ '@vueuse/metadata@10.9.0':
+ resolution: {integrity: sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==}
+
+ '@vueuse/shared@10.9.0':
+ resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
+
'@zeit/schemas@2.36.0':
resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
- confbox@0.1.7:
- resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==}
-
+ connect@3.7.0:
+ resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==}
+ engines: {node: '>= 0.10.0'}
+
constantinople@4.0.1:
resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==}
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
- electron-to-chromium@1.5.5:
- resolution: {integrity: sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==}
-
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
emoji-regex@10.3.0:
resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
++ fdir@6.3.0:
++ resolution: {integrity: sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==}
++ peerDependencies:
++ picomatch: ^3 || ^4
++ peerDependenciesMeta:
++ picomatch:
++ optional: true
++
+ fflate@0.8.2:
+ resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
+
file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
- mlly@1.7.1:
- resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
-
- monaco-editor@0.50.0:
- resolution: {integrity: sha512-8CclLCmrRRh+sul7C08BmPBP3P8wVWfBHomsTcndxg5NRCEPfu/mc2AGU8k37ajjDVXcXFc12ORAMUkmk+lkFA==}
+ monaco-editor@0.51.0:
+ resolution: {integrity: sha512-xaGwVV1fq343cM7aOYB6lVE4Ugf0UyimdD/x5PWcWBMKENwectaEu77FAN7c5sFiyumqeJdX1RPTh1ocioyDjw==}
+ mrmime@2.0.0:
+ resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
+ engines: {node: '>=10'}
+
ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
++ picomatch@4.0.2:
++ resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
++ engines: {node: '>=12'}
++
pidtree@0.6.0:
resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
engines: {node: '>=0.10'}
resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
engines: {node: '>=0.10.0'}
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
resolution: {integrity: sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==}
engines: {node: '>=14.18'}
- test-exclude@6.0.0:
- resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
- engines: {node: '>=8'}
+ terser@5.31.6:
+ resolution: {integrity: sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ test-exclude@7.0.1:
+ resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
+ engines: {node: '>=18'}
text-decoder@1.1.1:
resolution: {integrity: sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==}
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
- tinypool@0.8.4:
- resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==}
+ tinyexec@0.3.0:
+ resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==}
+
++ tinyglobby@0.2.6:
++ resolution: {integrity: sha512-NbBoFBpqfcgd1tCiO8Lkfdk+xrA7mlLR9zgvZcZWQQwU63XAfUePyd6wZBaU93Hqw347lHnwFzttAkemHzzz4g==}
++ engines: {node: '>=12.0.0'}
++
+ tinypool@1.0.0:
+ resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+
+ tinyrainbow@1.2.0:
+ resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
engines: {node: '>=14.0.0'}
- tinyspy@2.2.1:
- resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==}
+ tinyspy@3.0.0:
+ resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
engines: {node: '>=14.0.0'}
+ titleize@3.0.0:
+ resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==}
+ engines: {node: '>=12'}
+
to-fast-properties@2.0.0:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
engines: {node: '>=4'}
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
- update-browserslist-db@1.1.0:
- resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==}
- hasBin: true
- peerDependencies:
- browserslist: '>= 4.21.0'
-
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
+ untildify@4.0.0:
+ resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
+ engines: {node: '>=8'}
+
update-check@1.5.4:
resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==}
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
- vite-node@1.6.0:
- resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==}
+ vite-hyper-config@0.2.1:
+ resolution: {integrity: sha512-ItRIpzWp0XMh/Sn1H0GCWnQIUcBjnSaZy/EbOpJcRr9H/KTBHUSTCEOigE9K0KTN01Z0GDi/8WgVT9+RPL932A==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ vite: ^4.0.0 || ^5.0.0
+
+ vite-node@1.5.0:
+ resolution: {integrity: sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+
+ vite-node@2.1.1:
+ resolution: {integrity: sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
terser:
optional: true
- vitest@2.1.1:
- resolution: {integrity: sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==}
+ vite@5.3.3:
+ resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
+ vite@5.4.0:
+ resolution: {integrity: sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
- vitest@1.6.0:
- resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
++ vitest@2.1.1:
++ resolution: {integrity: sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
engines: {node: '>=0.10.0'}
- vue@3.5.0-beta.1:
- resolution: {integrity: sha512-17ZEyGr4411DWSNM9E0nNzQ4IPCkFPeDffTL17IFF+vCwinn9o5VyJmHexa2qKiwoLJ4Ib+3IGo+eAEgafW+fA==}
+ vue-demi@0.14.7:
+ resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+
++ vue@3.5.6:
++ resolution: {integrity: sha512-zv+20E2VIYbcJOzJPUWp03NOGFhMmpCKOfSxVTmCYyYFFko48H9tmuQFzYj7tu4qX1AeXlp9DmhIP89/sSxxhw==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
w3c-xmlserializer@5.0.0:
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
engines: {node: '>=18'}
'@esbuild/aix-ppc64@0.21.5':
optional: true
- '@esbuild/aix-ppc64@0.23.0':
+ '@esbuild/aix-ppc64@0.23.1':
optional: true
+ '@esbuild/android-arm64@0.20.2':
+ optional: true
+
'@esbuild/android-arm64@0.21.5':
optional: true
- '@esbuild/android-arm64@0.23.0':
+ '@esbuild/android-arm64@0.23.1':
optional: true
+ '@esbuild/android-arm@0.20.2':
+ optional: true
+
'@esbuild/android-arm@0.21.5':
optional: true
- '@esbuild/android-arm@0.23.0':
+ '@esbuild/android-arm@0.23.1':
optional: true
+ '@esbuild/android-x64@0.20.2':
+ optional: true
+
'@esbuild/android-x64@0.21.5':
optional: true
- '@esbuild/android-x64@0.23.0':
+ '@esbuild/android-x64@0.23.1':
optional: true
+ '@esbuild/darwin-arm64@0.20.2':
+ optional: true
+
'@esbuild/darwin-arm64@0.21.5':
optional: true
- '@esbuild/darwin-arm64@0.23.0':
+ '@esbuild/darwin-arm64@0.23.1':
optional: true
+ '@esbuild/darwin-x64@0.20.2':
+ optional: true
+
'@esbuild/darwin-x64@0.21.5':
optional: true
- '@esbuild/darwin-x64@0.23.0':
+ '@esbuild/darwin-x64@0.23.1':
optional: true
+ '@esbuild/freebsd-arm64@0.20.2':
+ optional: true
+
'@esbuild/freebsd-arm64@0.21.5':
optional: true
- '@esbuild/freebsd-arm64@0.23.0':
+ '@esbuild/freebsd-arm64@0.23.1':
optional: true
+ '@esbuild/freebsd-x64@0.20.2':
+ optional: true
+
'@esbuild/freebsd-x64@0.21.5':
optional: true
- '@esbuild/freebsd-x64@0.23.0':
+ '@esbuild/freebsd-x64@0.23.1':
optional: true
+ '@esbuild/linux-arm64@0.20.2':
+ optional: true
+
'@esbuild/linux-arm64@0.21.5':
optional: true
- '@esbuild/linux-arm64@0.23.0':
+ '@esbuild/linux-arm64@0.23.1':
optional: true
+ '@esbuild/linux-arm@0.20.2':
+ optional: true
+
'@esbuild/linux-arm@0.21.5':
optional: true
- '@esbuild/linux-arm@0.23.0':
+ '@esbuild/linux-arm@0.23.1':
optional: true
+ '@esbuild/linux-ia32@0.20.2':
+ optional: true
+
'@esbuild/linux-ia32@0.21.5':
optional: true
- '@esbuild/linux-ia32@0.23.0':
+ '@esbuild/linux-ia32@0.23.1':
optional: true
+ '@esbuild/linux-loong64@0.20.2':
+ optional: true
+
'@esbuild/linux-loong64@0.21.5':
optional: true
- '@esbuild/linux-loong64@0.23.0':
+ '@esbuild/linux-loong64@0.23.1':
optional: true
+ '@esbuild/linux-mips64el@0.20.2':
+ optional: true
+
'@esbuild/linux-mips64el@0.21.5':
optional: true
- '@esbuild/linux-mips64el@0.23.0':
+ '@esbuild/linux-mips64el@0.23.1':
optional: true
+ '@esbuild/linux-ppc64@0.20.2':
+ optional: true
+
'@esbuild/linux-ppc64@0.21.5':
optional: true
- '@esbuild/linux-ppc64@0.23.0':
+ '@esbuild/linux-ppc64@0.23.1':
optional: true
+ '@esbuild/linux-riscv64@0.20.2':
+ optional: true
+
'@esbuild/linux-riscv64@0.21.5':
optional: true
- '@esbuild/linux-riscv64@0.23.0':
+ '@esbuild/linux-riscv64@0.23.1':
optional: true
+ '@esbuild/linux-s390x@0.20.2':
+ optional: true
+
'@esbuild/linux-s390x@0.21.5':
optional: true
- '@esbuild/linux-s390x@0.23.0':
+ '@esbuild/linux-s390x@0.23.1':
optional: true
+ '@esbuild/linux-x64@0.20.2':
+ optional: true
+
'@esbuild/linux-x64@0.21.5':
optional: true
- '@esbuild/linux-x64@0.23.0':
+ '@esbuild/linux-x64@0.23.1':
optional: true
+ '@esbuild/netbsd-x64@0.20.2':
+ optional: true
+
'@esbuild/netbsd-x64@0.21.5':
optional: true
- '@esbuild/netbsd-x64@0.23.0':
+ '@esbuild/netbsd-x64@0.23.1':
optional: true
- '@esbuild/openbsd-arm64@0.23.0':
+ '@esbuild/openbsd-arm64@0.23.1':
optional: true
+ '@esbuild/openbsd-x64@0.20.2':
+ optional: true
+
'@esbuild/openbsd-x64@0.21.5':
optional: true
- '@esbuild/openbsd-x64@0.23.0':
+ '@esbuild/openbsd-x64@0.23.1':
optional: true
+ '@esbuild/sunos-x64@0.20.2':
+ optional: true
+
'@esbuild/sunos-x64@0.21.5':
optional: true
- '@esbuild/sunos-x64@0.23.0':
+ '@esbuild/sunos-x64@0.23.1':
optional: true
+ '@esbuild/win32-arm64@0.20.2':
+ optional: true
+
'@esbuild/win32-arm64@0.21.5':
optional: true
- '@esbuild/win32-arm64@0.23.0':
+ '@esbuild/win32-arm64@0.23.1':
optional: true
+ '@esbuild/win32-ia32@0.20.2':
+ optional: true
+
'@esbuild/win32-ia32@0.21.5':
optional: true
- '@esbuild/win32-ia32@0.23.0':
+ '@esbuild/win32-ia32@0.23.1':
optional: true
+ '@esbuild/win32-x64@0.20.2':
+ optional: true
+
'@esbuild/win32-x64@0.21.5':
optional: true
'@pkgjs/parseargs@0.11.0':
optional: true
- '@puppeteer/browsers@2.3.0':
+ '@polka/url@1.0.0-next.25': {}
+
+ '@puppeteer/browsers@2.4.0':
dependencies:
debug: 4.3.6
extract-zip: 2.0.1
'@tootallnate/quickjs-emscripten@0.23.0': {}
- '@types/node': 20.14.14
+ '@types/connect@3.4.38':
+ dependencies:
++ '@types/node': 20.16.5
+
'@types/estree@1.0.5': {}
'@types/hash-sum@1.0.2': {}
'@types/trusted-types@2.0.7': {}
+ '@types/web-bluetooth@0.0.20': {}
+
'@types/yauzl@2.10.3':
dependencies:
- '@types/node': 20.14.14
+ '@types/node': 20.16.5
optional: true
- '@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.1(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)':
+ '@typescript-eslint/eslint-plugin@8.5.0(@typescript-eslint/parser@8.5.0(eslint@9.10.0)(typescript@5.6.2))(eslint@9.10.0)(typescript@5.6.2)':
dependencies:
'@eslint-community/regexpp': 4.11.0
- '@typescript-eslint/parser': 8.0.1(eslint@9.8.0)(typescript@5.5.4)
- '@typescript-eslint/scope-manager': 8.0.1
- '@typescript-eslint/type-utils': 8.0.1(eslint@9.8.0)(typescript@5.5.4)
- '@typescript-eslint/utils': 8.0.1(eslint@9.8.0)(typescript@5.5.4)
- '@typescript-eslint/visitor-keys': 8.0.1
- eslint: 9.8.0
+ '@typescript-eslint/parser': 8.5.0(eslint@9.10.0)(typescript@5.6.2)
+ '@typescript-eslint/scope-manager': 8.5.0
+ '@typescript-eslint/type-utils': 8.5.0(eslint@9.10.0)(typescript@5.6.2)
+ '@typescript-eslint/utils': 8.5.0(eslint@9.10.0)(typescript@5.6.2)
+ '@typescript-eslint/visitor-keys': 8.5.0
+ eslint: 9.10.0
graphemer: 1.4.0
ignore: 5.3.1
natural-compare: 1.4.0
'@typescript-eslint/types': 7.18.0
eslint-visitor-keys: 3.4.3
- '@typescript-eslint/visitor-keys@8.0.1':
+ '@typescript-eslint/visitor-keys@8.5.0':
dependencies:
- '@typescript-eslint/types': 8.0.1
+ '@typescript-eslint/types': 8.5.0
eslint-visitor-keys: 3.4.3
- '@vitejs/plugin-vue@5.1.2(vite@5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))(vue@packages+vue)':
- '@vitejs/plugin-vue@5.1.2(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0))(vue@packages+vue)':
++ '@vitejs/plugin-vue@5.1.2(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@packages+vue)':
dependencies:
- vite: 5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
- vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
++ vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
vue: link:packages/vue
- '@vitest/coverage-istanbul@1.6.0(vitest@1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6))':
- '@vitest/coverage-v8@2.1.1(vitest@2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0))':
++ '@vitest/coverage-v8@2.1.1(vitest@2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6))':
dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@bcoe/v8-coverage': 0.2.3
debug: 4.3.6
istanbul-lib-coverage: 3.2.2
- istanbul-lib-instrument: 6.0.3
istanbul-lib-report: 3.0.1
istanbul-lib-source-maps: 5.0.6
istanbul-reports: 3.1.7
+ magic-string: 0.30.11
magicast: 0.3.4
- picocolors: 1.0.1
- test-exclude: 6.0.0
- vitest: 1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6)
+ std-env: 3.7.0
+ test-exclude: 7.0.1
+ tinyrainbow: 1.2.0
- vitest: 2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0)
++ vitest: 2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6)
transitivePeerDependencies:
- supports-color
- '@vitest/expect@1.6.0':
+ '@vitest/expect@2.1.1':
dependencies:
- '@vitest/spy': 1.6.0
- '@vitest/utils': 1.6.0
- chai: 4.5.0
+ '@vitest/spy': 2.1.1
+ '@vitest/utils': 2.1.1
+ chai: 5.1.1
+ tinyrainbow: 1.2.0
- '@vitest/runner@1.6.0':
- '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0))':
++ '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))':
dependencies:
- '@vitest/utils': 1.6.0
- p-limit: 5.0.0
+ '@vitest/spy': 2.1.1
+ estree-walker: 3.0.3
+ magic-string: 0.30.11
+ optionalDependencies:
- vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
++ vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+
+ '@vitest/pretty-format@2.1.1':
+ dependencies:
+ tinyrainbow: 1.2.0
+
+ '@vitest/runner@2.1.1':
+ dependencies:
+ '@vitest/utils': 2.1.1
pathe: 1.1.2
- '@vitest/snapshot@1.6.0':
+ '@vitest/snapshot@2.1.1':
dependencies:
+ '@vitest/pretty-format': 2.1.1
magic-string: 0.30.11
pathe: 1.1.2
- pretty-format: 29.7.0
- '@vitest/spy@1.6.0':
+ '@vitest/spy@2.1.1':
dependencies:
- tinyspy: 2.2.1
+ tinyspy: 3.0.0
- '@vitest/ui@1.6.0(vitest@1.6.0)':
++ '@vitest/ui@2.1.1(vitest@2.1.1)':
+ dependencies:
- '@vitest/utils': 1.6.0
- fast-glob: 3.3.2
++ '@vitest/utils': 2.1.1
+ fflate: 0.8.2
+ flatted: 3.3.1
+ pathe: 1.1.2
- picocolors: 1.0.1
+ sirv: 2.0.4
- vitest: 1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6)
++ tinyglobby: 0.2.6
++ tinyrainbow: 1.2.0
++ vitest: 2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6)
+
- '@vitest/utils@1.6.0':
+ '@vitest/utils@2.1.1':
dependencies:
- diff-sequences: 29.6.3
- estree-walker: 3.0.3
- loupe: 2.3.7
- pretty-format: 29.7.0
+ '@vitest/pretty-format': 2.1.1
+ loupe: 3.1.1
+ tinyrainbow: 1.2.0
- '@vue-vapor/vite-plugin-vue@0.0.0-alpha.4(vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))(vue@packages+vue)':
++ '@vue-vapor/vite-plugin-vue@0.0.0-alpha.4(vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@packages+vue)':
+ dependencies:
- vite: 5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
++ vite: 5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ vue: link:packages/vue
+
- '@vue-vapor/vite-plugin-vue@0.0.0-alpha.6(vite@5.3.3(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6))(vue@3.5.0-beta.1(typescript@5.5.4))':
++ '@vue-vapor/vite-plugin-vue@0.0.0-alpha.6(vite@5.3.3(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))(vue@3.5.6(typescript@5.6.2))':
+ dependencies:
- vite: 5.3.3(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
- vue: 3.5.0-beta.1(typescript@5.5.4)
++ vite: 5.3.3(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
++ vue: 3.5.6(typescript@5.6.2)
+
- '@vue/compiler-core@3.5.0-beta.1':
++ '@vue/compiler-core@3.5.6':
+ dependencies:
+ '@babel/parser': 7.25.3
- '@vue/shared': 3.5.0-beta.1
- entities: 5.0.0
++ '@vue/shared': 3.5.6
++ entities: 4.5.0
+ estree-walker: 2.0.2
- source-map-js: 1.2.0
++ source-map-js: 1.2.1
+
- '@vue/compiler-dom@3.5.0-beta.1':
++ '@vue/compiler-dom@3.5.6':
+ dependencies:
- '@vue/compiler-core': 3.5.0-beta.1
- '@vue/shared': 3.5.0-beta.1
++ '@vue/compiler-core': 3.5.6
++ '@vue/shared': 3.5.6
+
- '@vue/compiler-sfc@3.5.0-beta.1':
++ '@vue/compiler-sfc@3.5.6':
+ dependencies:
+ '@babel/parser': 7.25.3
- '@vue/compiler-core': 3.5.0-beta.1
- '@vue/compiler-dom': 3.5.0-beta.1
- '@vue/compiler-ssr': 3.5.0-beta.1
- '@vue/shared': 3.5.0-beta.1
++ '@vue/compiler-core': 3.5.6
++ '@vue/compiler-dom': 3.5.6
++ '@vue/compiler-ssr': 3.5.6
++ '@vue/shared': 3.5.6
+ estree-walker: 2.0.2
+ magic-string: 0.30.11
- postcss: 8.4.41
- source-map-js: 1.2.0
++ postcss: 8.4.47
++ source-map-js: 1.2.1
+
- '@vue/compiler-ssr@3.5.0-beta.1':
++ '@vue/compiler-ssr@3.5.6':
+ dependencies:
- '@vue/compiler-dom': 3.5.0-beta.1
- '@vue/shared': 3.5.0-beta.1
++ '@vue/compiler-dom': 3.5.6
++ '@vue/shared': 3.5.6
+
'@vue/consolidate@1.0.0': {}
- '@vue/reactivity@3.5.0-beta.1':
++ '@vue/reactivity@3.5.6':
+ dependencies:
- '@vue/shared': 3.5.0-beta.1
++ '@vue/shared': 3.5.6
+
- '@vue/repl@4.3.1': {}
+ '@vue/repl@4.4.2': {}
- '@vue/runtime-core@3.5.0-beta.1':
++ '@vue/runtime-core@3.5.6':
+ dependencies:
- '@vue/reactivity': 3.5.0-beta.1
- '@vue/shared': 3.5.0-beta.1
++ '@vue/reactivity': 3.5.6
++ '@vue/shared': 3.5.6
+
- '@vue/runtime-dom@3.5.0-beta.1':
++ '@vue/runtime-dom@3.5.6':
+ dependencies:
- '@vue/reactivity': 3.5.0-beta.1
- '@vue/runtime-core': 3.5.0-beta.1
- '@vue/shared': 3.5.0-beta.1
++ '@vue/reactivity': 3.5.6
++ '@vue/runtime-core': 3.5.6
++ '@vue/shared': 3.5.6
+ csstype: 3.1.3
+
- '@vue/server-renderer@3.5.0-beta.1(vue@3.5.0-beta.1(typescript@5.5.4))':
++ '@vue/server-renderer@3.5.6(vue@3.5.6(typescript@5.6.2))':
+ dependencies:
- '@vue/compiler-ssr': 3.5.0-beta.1
- '@vue/shared': 3.5.0-beta.1
- vue: 3.5.0-beta.1(typescript@5.5.4)
++ '@vue/compiler-ssr': 3.5.6
++ '@vue/shared': 3.5.6
++ vue: 3.5.6(typescript@5.6.2)
+
- '@vue/shared@3.5.0-beta.1': {}
++ '@vue/shared@3.5.6': {}
+
+ '@vueuse/core@10.9.0(vue@packages+vue)':
+ dependencies:
+ '@types/web-bluetooth': 0.0.20
+ '@vueuse/metadata': 10.9.0
+ '@vueuse/shared': 10.9.0(vue@packages+vue)
+ vue-demi: 0.14.7(vue@packages+vue)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+
+ '@vueuse/metadata@10.9.0': {}
+
+ '@vueuse/shared@10.9.0(vue@packages+vue)':
+ dependencies:
+ vue-demi: 0.14.7(vue@packages+vue)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+
'@zeit/schemas@2.36.0': {}
accepts@1.3.8:
dependencies:
fill-range: 7.1.1
- browserslist@4.23.3:
- dependencies:
- caniuse-lite: 1.0.30001651
- electron-to-chromium: 1.5.5
- node-releases: 2.0.18
- update-browserslist-db: 1.1.0(browserslist@4.23.3)
-
buffer-crc32@0.2.13: {}
+ buffer-from@1.1.2: {}
+
buffer@5.7.1:
dependencies:
base64-js: 1.5.1
concat-map@0.0.1: {}
- confbox@0.1.7: {}
-
+ connect@3.7.0:
+ dependencies:
+ debug: 2.6.9
+ finalhandler: 1.1.2
+ parseurl: 1.3.3
+ utils-merge: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
constantinople@4.0.1:
dependencies:
'@babel/parser': 7.25.3
eastasianwidth@0.2.0: {}
- electron-to-chromium@1.5.5: {}
-
+ ee-first@1.1.1: {}
+
emoji-regex@10.3.0: {}
emoji-regex@8.0.0: {}
es-module-lexer@1.5.4: {}
- esbuild-plugin-polyfill-node@0.3.0(esbuild@0.23.0):
+ esbuild-plugin-polyfill-node@0.3.0(esbuild@0.23.1):
dependencies:
'@jspm/core': 2.0.1
- esbuild: 0.23.0
+ esbuild: 0.23.1
import-meta-resolve: 3.1.1
+ esbuild@0.20.2:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.20.2
+ '@esbuild/android-arm': 0.20.2
+ '@esbuild/android-arm64': 0.20.2
+ '@esbuild/android-x64': 0.20.2
+ '@esbuild/darwin-arm64': 0.20.2
+ '@esbuild/darwin-x64': 0.20.2
+ '@esbuild/freebsd-arm64': 0.20.2
+ '@esbuild/freebsd-x64': 0.20.2
+ '@esbuild/linux-arm': 0.20.2
+ '@esbuild/linux-arm64': 0.20.2
+ '@esbuild/linux-ia32': 0.20.2
+ '@esbuild/linux-loong64': 0.20.2
+ '@esbuild/linux-mips64el': 0.20.2
+ '@esbuild/linux-ppc64': 0.20.2
+ '@esbuild/linux-riscv64': 0.20.2
+ '@esbuild/linux-s390x': 0.20.2
+ '@esbuild/linux-x64': 0.20.2
+ '@esbuild/netbsd-x64': 0.20.2
+ '@esbuild/openbsd-x64': 0.20.2
+ '@esbuild/sunos-x64': 0.20.2
+ '@esbuild/win32-arm64': 0.20.2
+ '@esbuild/win32-ia32': 0.20.2
+ '@esbuild/win32-x64': 0.20.2
+
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
- supports-color
- typescript
- eslint-plugin-vitest@0.5.4(eslint@9.8.0)(typescript@5.5.4)(vitest@1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6)):
- eslint-plugin-vitest@0.5.4(eslint@9.10.0)(typescript@5.6.2)(vitest@2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0)):
++ eslint-plugin-vitest@0.5.4(eslint@9.10.0)(typescript@5.6.2)(vitest@2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6)):
dependencies:
- '@typescript-eslint/utils': 7.18.0(eslint@9.8.0)(typescript@5.5.4)
- eslint: 9.8.0
+ '@typescript-eslint/utils': 7.18.0(eslint@9.10.0)(typescript@5.6.2)
+ eslint: 9.10.0
optionalDependencies:
- vitest: 1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6)
- vitest: 2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0)
++ vitest: 2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6)
transitivePeerDependencies:
- supports-color
- typescript
dependencies:
pend: 1.2.0
++ fdir@6.3.0(picomatch@4.0.2):
++ optionalDependencies:
++ picomatch: 4.0.2
++
+ fflate@0.8.2: {}
+
file-entry-cache@8.0.0:
dependencies:
flat-cache: 4.0.1
mitt@3.0.1: {}
- mlly@1.7.1:
- dependencies:
- acorn: 8.12.1
- pathe: 1.1.2
- pkg-types: 1.1.3
- ufo: 1.5.4
-
- monaco-editor@0.50.0: {}
+ monaco-editor@0.51.0: {}
+ mrmime@2.0.0: {}
+
ms@2.0.0: {}
ms@2.1.2: {}
dependencies:
entities: 4.5.0
+ parseurl@1.3.3: {}
+
path-exists@4.0.0: {}
- path-is-absolute@1.0.1: {}
-
path-is-inside@1.0.2: {}
path-key@3.1.1: {}
picocolors@1.0.1: {}
+ picocolors@1.1.0: {}
+
picomatch@2.3.1: {}
- pidtree@0.6.0: {}
++ picomatch@4.0.2: {}
+
- pkg-types@1.1.3:
- dependencies:
- confbox: 0.1.7
- mlly: 1.7.1
- pathe: 1.1.2
+ pidtree@0.6.0: {}
- postcss-modules-extract-imports@3.1.0(postcss@8.4.41):
+ postcss-modules-extract-imports@3.1.0(postcss@8.4.47):
dependencies:
- postcss: 8.4.41
+ postcss: 8.4.47
- postcss-modules-local-by-default@4.0.5(postcss@8.4.41):
+ postcss-modules-local-by-default@4.0.5(postcss@8.4.47):
dependencies:
- icss-utils: 5.1.0(postcss@8.4.41)
- postcss: 8.4.41
- postcss-selector-parser: 6.1.1
+ icss-utils: 5.1.0(postcss@8.4.47)
+ postcss: 8.4.47
+ postcss-selector-parser: 6.1.2
postcss-value-parser: 4.2.0
- postcss-modules-scope@3.2.0(postcss@8.4.41):
+ postcss-modules-scope@3.2.0(postcss@8.4.47):
dependencies:
- postcss: 8.4.41
- postcss-selector-parser: 6.1.1
+ postcss: 8.4.47
+ postcss-selector-parser: 6.1.2
- postcss-modules-values@4.0.0(postcss@8.4.41):
+ postcss-modules-values@4.0.0(postcss@8.4.47):
dependencies:
- icss-utils: 5.1.0(postcss@8.4.41)
- postcss: 8.4.41
+ icss-utils: 5.1.0(postcss@8.4.47)
+ postcss: 8.4.47
- postcss-modules@6.0.0(postcss@8.4.41):
+ postcss-modules@6.0.0(postcss@8.4.47):
dependencies:
generic-names: 4.0.0
- icss-utils: 5.1.0(postcss@8.4.41)
+ icss-utils: 5.1.0(postcss@8.4.47)
lodash.camelcase: 4.3.0
- postcss: 8.4.41
- postcss-modules-extract-imports: 3.1.0(postcss@8.4.41)
- postcss-modules-local-by-default: 4.0.5(postcss@8.4.41)
- postcss-modules-scope: 3.2.0(postcss@8.4.41)
- postcss-modules-values: 4.0.0(postcss@8.4.41)
+ postcss: 8.4.47
+ postcss-modules-extract-imports: 3.1.0(postcss@8.4.47)
+ postcss-modules-local-by-default: 4.0.5(postcss@8.4.47)
+ postcss-modules-scope: 3.2.0(postcss@8.4.47)
+ postcss-modules-values: 4.0.0(postcss@8.4.47)
string-hash: 1.1.3
- postcss-selector-parser@6.1.1:
+ postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
source-map-js@1.2.0: {}
+ source-map-js@1.2.1: {}
+
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
source-map@0.6.1: {}
spdx-correct@3.2.0:
dependencies:
temp-dir: 3.0.0
- test-exclude@6.0.0:
+ terser@5.31.6:
+ dependencies:
+ '@jridgewell/source-map': 0.3.6
+ acorn: 8.12.1
+ commander: 2.20.3
+ source-map-support: 0.5.21
+
+ test-exclude@7.0.1:
dependencies:
'@istanbuljs/schema': 0.1.3
- glob: 7.2.3
- minimatch: 3.1.2
+ glob: 10.4.5
+ minimatch: 9.0.5
text-decoder@1.1.1:
dependencies:
tinybench@2.9.0: {}
- tinypool@0.8.4: {}
+ tinyexec@0.3.0: {}
- tinyspy@2.2.1: {}
++ tinyglobby@0.2.6:
++ dependencies:
++ fdir: 6.3.0(picomatch@4.0.2)
++ picomatch: 4.0.2
++
+ tinypool@1.0.0: {}
+
+ tinyrainbow@1.2.0: {}
+
+ tinyspy@3.0.0: {}
+ titleize@3.0.0: {}
+
to-fast-properties@2.0.0: {}
to-regex-range@5.0.1:
universalify@2.0.1: {}
- update-browserslist-db@1.1.0(browserslist@4.23.3):
- dependencies:
- browserslist: 4.23.3
- escalade: 3.1.2
- picocolors: 1.0.1
-
+ unpipe@1.0.0: {}
+
+ untildify@4.0.0: {}
+
update-check@1.5.4:
dependencies:
registry-auth-token: 3.3.2
vary@1.1.2: {}
- vite-hyper-config@0.2.1(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)(vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)):
- vite-node@2.1.1(@types/node@20.16.5)(sass@1.78.0):
++ vite-hyper-config@0.2.1(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)(vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)):
+ dependencies:
+ cac: 6.7.14
+ picocolors: 1.0.1
- vite: 5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
- vite-node: 1.5.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
++ vite: 5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
++ vite-node: 1.5.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
- vite-node@1.5.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6):
++ vite-node@1.5.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.3.6
+ pathe: 1.1.2
+ picocolors: 1.0.1
- vite: 5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
++ vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
- vite-node@1.6.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6):
++ vite-node@2.1.1(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6):
dependencies:
cac: 6.7.14
debug: 4.3.6
pathe: 1.1.2
- picocolors: 1.0.1
- vite: 5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
- vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
++ vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
transitivePeerDependencies:
- '@types/node'
- less
- supports-color
- terser
- vite-plugin-inspect@0.7.42(rollup@4.20.0)(vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)):
- vite@5.4.0(@types/node@20.16.5)(sass@1.78.0):
++ vite-plugin-inspect@0.7.42(rollup@4.21.3)(vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)):
+ dependencies:
+ '@antfu/utils': 0.7.7
- '@rollup/pluginutils': 5.1.0(rollup@4.20.0)
++ '@rollup/pluginutils': 5.1.0(rollup@4.21.3)
+ debug: 4.3.6
+ error-stack-parser-es: 0.1.1
+ fs-extra: 11.2.0
+ open: 9.1.0
+ picocolors: 1.0.1
+ sirv: 2.0.4
- vite: 5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
++ vite: 5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
+ transitivePeerDependencies:
+ - rollup
+ - supports-color
+
- vite@5.2.9(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6):
++ vite@5.2.9(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6):
+ dependencies:
+ esbuild: 0.20.2
+ postcss: 8.4.41
+ rollup: 4.20.0
+ optionalDependencies:
- '@types/node': 20.14.14
++ '@types/node': 20.16.5
+ fsevents: 2.3.3
- sass: 1.77.8
++ sass: 1.78.0
+ terser: 5.31.6
+
- vite@5.3.3(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6):
++ vite@5.3.3(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6):
dependencies:
esbuild: 0.21.5
postcss: 8.4.41
rollup: 4.20.0
optionalDependencies:
- '@types/node': 20.14.14
+ '@types/node': 20.16.5
fsevents: 2.3.3
- sass: 1.77.8
+ sass: 1.78.0
+ terser: 5.31.6
- vite@5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6):
- vitest@2.1.1(@types/node@20.16.5)(jsdom@25.0.0)(sass@1.78.0):
++ vite@5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6):
+ dependencies:
+ esbuild: 0.21.5
- postcss: 8.4.41
- rollup: 4.20.0
++ postcss: 8.4.47
++ rollup: 4.21.3
+ optionalDependencies:
- '@types/node': 20.14.14
++ '@types/node': 20.16.5
+ fsevents: 2.3.3
- sass: 1.77.8
++ sass: 1.78.0
+ terser: 5.31.6
+
- vitest@1.6.0(@types/node@20.14.14)(@vitest/ui@1.6.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.6):
++ vitest@2.1.1(@types/node@20.16.5)(@vitest/ui@2.1.1)(jsdom@25.0.0)(sass@1.78.0)(terser@5.31.6):
dependencies:
- '@vitest/expect': 1.6.0
- '@vitest/runner': 1.6.0
- '@vitest/snapshot': 1.6.0
- '@vitest/spy': 1.6.0
- '@vitest/utils': 1.6.0
- acorn-walk: 8.3.3
- chai: 4.5.0
+ '@vitest/expect': 2.1.1
- '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0))
++ '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6))
+ '@vitest/pretty-format': 2.1.1
+ '@vitest/runner': 2.1.1
+ '@vitest/snapshot': 2.1.1
+ '@vitest/spy': 2.1.1
+ '@vitest/utils': 2.1.1
+ chai: 5.1.1
debug: 4.3.6
- execa: 8.0.1
- local-pkg: 0.5.0
magic-string: 0.30.11
pathe: 1.1.2
- picocolors: 1.0.1
std-env: 3.7.0
- strip-literal: 2.1.0
tinybench: 2.9.0
- tinypool: 0.8.4
- vite: 5.4.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
- vite-node: 1.6.0(@types/node@20.14.14)(sass@1.77.8)(terser@5.31.6)
+ tinyexec: 0.3.0
+ tinypool: 1.0.0
+ tinyrainbow: 1.2.0
- vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)
- vite-node: 2.1.1(@types/node@20.16.5)(sass@1.78.0)
++ vite: 5.4.0(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
++ vite-node: 2.1.1(@types/node@20.16.5)(sass@1.78.0)(terser@5.31.6)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 20.14.14
- '@vitest/ui': 1.6.0(vitest@1.6.0)
- jsdom: 24.1.1
+ '@types/node': 20.16.5
++ '@vitest/ui': 2.1.1(vitest@2.1.1)
+ jsdom: 25.0.0
transitivePeerDependencies:
- less
- lightningcss
void-elements@3.1.0: {}
- vue@3.5.0-beta.1(typescript@5.5.4):
+ vue-demi@0.14.7(vue@packages+vue):
+ dependencies:
+ vue: link:packages/vue
+
- '@vue/compiler-dom': 3.5.0-beta.1
- '@vue/compiler-sfc': 3.5.0-beta.1
- '@vue/runtime-dom': 3.5.0-beta.1
- '@vue/server-renderer': 3.5.0-beta.1(vue@3.5.0-beta.1(typescript@5.5.4))
- '@vue/shared': 3.5.0-beta.1
++ vue@3.5.6(typescript@5.6.2):
+ dependencies:
- typescript: 5.5.4
++ '@vue/compiler-dom': 3.5.6
++ '@vue/compiler-sfc': 3.5.6
++ '@vue/runtime-dom': 3.5.6
++ '@vue/server-renderer': 3.5.6(vue@3.5.6(typescript@5.6.2))
++ '@vue/shared': 3.5.6
+ optionalDependencies:
++ typescript: 5.6.2
+
w3c-xmlserializer@5.0.0:
dependencies:
xml-name-validator: 5.0.0
packages:
- 'packages/*'
+ - 'packages-private/*'
+ - playground
+ - benchmark
catalog:
'@babel/parser': ^7.25.3
import { minify } from '@swc/core'
import replace from '@rollup/plugin-replace'
import { brotliCompressSync, gzipSync } from 'node:zlib'
+ import { parseArgs } from 'node:util'
+ import pico from 'picocolors'
+ import prettyBytes from 'pretty-bytes'
+
+ const {
+ values: { write },
+ } = parseArgs({
+ options: {
+ write: {
+ type: 'boolean',
+ default: false,
+ },
+ },
+ })
const sizeDir = path.resolve('temp/size')
-const entry = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js')
+const vue = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js')
+const vapor = path.resolve(
+ './packages/vue-vapor/dist/vue-vapor.runtime.esm-bundler.js',
+)
- interface Preset {
- name: string
- imports: '*' | string[]
- from: string
- }
+ /**
+ * @typedef {Object} Preset
+ * @property {string} name - The name of the preset
- * @property {string[]} imports - The imports that are part of this preset
++ * @property {'*' | string[]} imports - The imports that are part of this preset
++ * @property {string} from - The path to the entry file
+ * @property {Record<string, string>} [replace]
+ */
- const presets: Preset[] = [
- { name: 'createApp', imports: ['createApp'], from: vue },
- { name: 'createSSRApp', imports: ['createSSRApp'], from: vue },
+ /** @type {Preset[]} */
+ const presets = [
{
- name: 'defineCustomElement',
- imports: ['defineCustomElement'],
+ name: 'createApp (CAPI only)',
+ imports: ['createApp'],
+ replace: { __VUE_OPTIONS_API__: 'false' },
+ from: vue,
},
- { name: 'createApp', imports: ['createApp'] },
- { name: 'createSSRApp', imports: ['createSSRApp'] },
- { name: 'defineCustomElement', imports: ['defineCustomElement'] },
++ { name: 'createApp', imports: ['createApp'], from: vue },
++ { name: 'createSSRApp', imports: ['createSSRApp'], from: vue },
++ { name: 'defineCustomElement', imports: ['defineCustomElement'], from: vue },
+ { name: 'vapor', imports: '*', from: vapor },
{
name: 'overall',
imports: [
)
}
- async function generateBundle(preset: Preset) {
+ /**
+ * Generates a bundle for a given preset
+ *
+ * @param {Preset} preset - The preset to generate the bundle for
+ * @returns {Promise<{name: string, size: number, gzip: number, brotli: number}>} - The result of the bundling process
+ */
+ async function generateBundle(preset) {
const id = 'virtual:entry'
- const content = `export { ${preset.imports.join(', ')} } from '${entry}'`
-
+ const exportSpecifiers =
+ preset.imports === '*'
+ ? `* as ${preset.name}`
+ : `{ ${preset.imports.join(', ')} }`
+ const content = `export ${exportSpecifiers} from '${preset.from}'`
const result = await rollup({
input: id,
plugins: [
},
test: {
globals: true,
+ pool: 'threads',
setupFiles: 'scripts/setup-vitest.ts',
environmentMatchGlobs: [
- ['packages/{vue,vue-compat,runtime-dom}/**', 'jsdom'],
+ ['packages/{vue,vue-compat,runtime-dom,runtime-vapor}/**', 'jsdom'],
],
sequence: {
hooks: 'list',