├── .git-blame-ignore-revs ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── config.yml ├── bug-repro-guidelines.md ├── commit-convention.md ├── contributing.md ├── git-branch-workflow.excalidraw ├── git-branch-workflow.png ├── issue-workflow.png ├── maintenance.md ├── renovate.json5 └── workflows │ ├── autofix.yml │ ├── canary-minor.yml │ ├── canary.yml │ ├── ci.yml │ ├── close-cant-reproduce-issues.yml │ ├── ecosystem-ci-trigger.yml │ ├── lock-closed-issues.yml │ ├── release.yml │ ├── size-data.yml │ ├── size-report.yml │ └── test.yml ├── .gitignore ├── .node-version ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── .well-known └── funding-manifest-urls ├── BACKERS.md ├── CHANGELOG.md ├── FUNDING.json ├── LICENSE ├── README.md ├── SECURITY.md ├── changelogs ├── CHANGELOG-3.0.md ├── CHANGELOG-3.1.md ├── CHANGELOG-3.2.md ├── CHANGELOG-3.3.md └── CHANGELOG-3.4.md ├── eslint.config.js ├── netlify.toml ├── package.json ├── packages-private ├── dts-built-test │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── dts-test │ ├── README.md │ ├── appDirective.test-d.ts │ ├── appUse.test-d.ts │ ├── built.test-d.ts │ ├── compiler.test-d.ts │ ├── component.test-d.ts │ ├── componentInstance.test-d.tsx │ ├── componentTypeExtensions.test-d.tsx │ ├── defineComponent.test-d.tsx │ ├── defineCustomElement.test-d.ts │ ├── directives.test-d.ts │ ├── extractProps.test-d.ts │ ├── functionalComponent.test-d.tsx │ ├── h.test-d.ts │ ├── inject.test-d.ts │ ├── package.json │ ├── reactivity.test-d.ts │ ├── ref.test-d.ts │ ├── setupHelpers.test-d.ts │ ├── tsconfig.test.json │ ├── tsx.test-d.tsx │ ├── utils.d.ts │ └── watch.test-d.ts ├── global.d.ts ├── sfc-playground │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ └── logo.svg │ ├── src │ │ ├── App.vue │ │ ├── Header.vue │ │ ├── VersionSelect.vue │ │ ├── download │ │ │ ├── download.ts │ │ │ └── template │ │ │ │ ├── README.md │ │ │ │ ├── index.html │ │ │ │ ├── main.js │ │ │ │ ├── package.json │ │ │ │ └── vite.config.js │ │ ├── icons │ │ │ ├── Copy.vue │ │ │ ├── Download.vue │ │ │ ├── GitHub.vue │ │ │ ├── Moon.vue │ │ │ ├── Reload.vue │ │ │ ├── Share.vue │ │ │ └── Sun.vue │ │ ├── main.ts │ │ ├── vue-dev-proxy-prod.ts │ │ ├── vue-dev-proxy.ts │ │ └── vue-server-renderer-dev-proxy.ts │ ├── vercel.json │ └── vite.config.ts ├── template-explorer │ ├── README.md │ ├── _redirects │ ├── index.html │ ├── local.html │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── options.ts │ │ └── theme.ts │ └── style.css ├── tsconfig.json └── vite-debug │ ├── App.vue │ ├── README.md │ ├── index.html │ ├── main.ts │ ├── package.json │ ├── tsconfig.json │ └── vite.config.ts ├── packages ├── compiler-core │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── codegen.spec.ts.snap │ │ │ ├── compile.spec.ts.snap │ │ │ ├── parse.spec.ts.snap │ │ │ └── scopeId.spec.ts.snap │ │ ├── codegen.spec.ts │ │ ├── compile.spec.ts │ │ ├── parse.spec.ts │ │ ├── scopeId.spec.ts │ │ ├── testUtils.ts │ │ ├── transform.spec.ts │ │ ├── transforms │ │ │ ├── __snapshots__ │ │ │ │ ├── cacheStatic.spec.ts.snap │ │ │ │ ├── transformElement.spec.ts.snap │ │ │ │ ├── transformExpressions.spec.ts.snap │ │ │ │ ├── transformText.spec.ts.snap │ │ │ │ ├── vFor.spec.ts.snap │ │ │ │ ├── vIf.spec.ts.snap │ │ │ │ ├── vMemo.spec.ts.snap │ │ │ │ ├── vModel.spec.ts.snap │ │ │ │ ├── vOnce.spec.ts.snap │ │ │ │ └── vSlot.spec.ts.snap │ │ │ ├── cacheStatic.spec.ts │ │ │ ├── noopDirectiveTransform.spec.ts │ │ │ ├── transformElement.spec.ts │ │ │ ├── transformExpressions.spec.ts │ │ │ ├── transformSlotOutlet.spec.ts │ │ │ ├── transformText.spec.ts │ │ │ ├── vBind.spec.ts │ │ │ ├── vFor.spec.ts │ │ │ ├── vIf.spec.ts │ │ │ ├── vMemo.spec.ts │ │ │ ├── vModel.spec.ts │ │ │ ├── vOn.spec.ts │ │ │ ├── vOnce.spec.ts │ │ │ └── vSlot.spec.ts │ │ └── utils.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── ast.ts │ │ ├── babelUtils.ts │ │ ├── codegen.ts │ │ ├── compat │ │ ├── compatConfig.ts │ │ └── transformFilter.ts │ │ ├── compile.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── options.ts │ │ ├── parser.ts │ │ ├── runtimeHelpers.ts │ │ ├── tokenizer.ts │ │ ├── transform.ts │ │ ├── transforms │ │ ├── cacheStatic.ts │ │ ├── noopDirectiveTransform.ts │ │ ├── transformElement.ts │ │ ├── transformExpression.ts │ │ ├── transformSlotOutlet.ts │ │ ├── transformText.ts │ │ ├── vBind.ts │ │ ├── vFor.ts │ │ ├── vIf.ts │ │ ├── vMemo.ts │ │ ├── vModel.ts │ │ ├── vOn.ts │ │ ├── vOnce.ts │ │ └── vSlot.ts │ │ ├── utils.ts │ │ └── validateExpression.ts ├── compiler-dom │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── index.spec.ts.snap │ │ ├── decoderHtmlBrowser.spec.ts │ │ ├── index.spec.ts │ │ ├── parse.spec.ts │ │ └── transforms │ │ │ ├── Transition.spec.ts │ │ │ ├── __snapshots__ │ │ │ ├── Transition.spec.ts.snap │ │ │ ├── stringifyStatic.spec.ts.snap │ │ │ ├── vModel.spec.ts.snap │ │ │ └── vShow.spec.ts.snap │ │ │ ├── ignoreSideEffectTags.spec.ts │ │ │ ├── stringifyStatic.spec.ts │ │ │ ├── transformStyle.spec.ts │ │ │ ├── vHtml.spec.ts │ │ │ ├── vModel.spec.ts │ │ │ ├── vOn.spec.ts │ │ │ ├── vShow.spec.ts │ │ │ ├── vText.spec.ts │ │ │ └── validateHtmlNesting.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── decodeHtmlBrowser.ts │ │ ├── errors.ts │ │ ├── htmlNesting.ts │ │ ├── index.ts │ │ ├── parserOptions.ts │ │ ├── runtimeHelpers.ts │ │ └── transforms │ │ ├── Transition.ts │ │ ├── ignoreSideEffectTags.ts │ │ ├── stringifyStatic.ts │ │ ├── transformStyle.ts │ │ ├── vHtml.ts │ │ ├── vModel.ts │ │ ├── vOn.ts │ │ ├── vShow.ts │ │ ├── vText.ts │ │ └── validateHtmlNesting.ts ├── compiler-sfc │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── compileScript.spec.ts.snap │ │ │ ├── compileTemplate.spec.ts.snap │ │ │ ├── cssVars.spec.ts.snap │ │ │ ├── templateTransformAssetUrl.spec.ts.snap │ │ │ └── templateTransformSrcset.spec.ts.snap │ │ ├── compileScript.spec.ts │ │ ├── compileScript │ │ │ ├── __snapshots__ │ │ │ │ ├── defineEmits.spec.ts.snap │ │ │ │ ├── defineExpose.spec.ts.snap │ │ │ │ ├── defineModel.spec.ts.snap │ │ │ │ ├── defineOptions.spec.ts.snap │ │ │ │ ├── defineProps.spec.ts.snap │ │ │ │ ├── definePropsDestructure.spec.ts.snap │ │ │ │ ├── defineSlots.spec.ts.snap │ │ │ │ ├── hoistStatic.spec.ts.snap │ │ │ │ └── importUsageCheck.spec.ts.snap │ │ │ ├── defineEmits.spec.ts │ │ │ ├── defineExpose.spec.ts │ │ │ ├── defineModel.spec.ts │ │ │ ├── defineOptions.spec.ts │ │ │ ├── defineProps.spec.ts │ │ │ ├── definePropsDestructure.spec.ts │ │ │ ├── defineSlots.spec.ts │ │ │ ├── hoistStatic.spec.ts │ │ │ ├── importUsageCheck.spec.ts │ │ │ └── resolveType.spec.ts │ │ ├── compileStyle.spec.ts │ │ ├── compileTemplate.spec.ts │ │ ├── cssVars.spec.ts │ │ ├── fixture │ │ │ └── import.scss │ │ ├── parse.spec.ts │ │ ├── rewriteDefault.spec.ts │ │ ├── templateTransformAssetUrl.spec.ts │ │ ├── templateTransformSrcset.spec.ts │ │ ├── templateUtils.spec.ts │ │ └── utils.ts │ ├── package.json │ └── src │ │ ├── cache.ts │ │ ├── compileScript.ts │ │ ├── compileStyle.ts │ │ ├── compileTemplate.ts │ │ ├── index.ts │ │ ├── parse.ts │ │ ├── rewriteDefault.ts │ │ ├── script │ │ ├── analyzeScriptBindings.ts │ │ ├── context.ts │ │ ├── defineEmits.ts │ │ ├── defineExpose.ts │ │ ├── defineModel.ts │ │ ├── defineOptions.ts │ │ ├── defineProps.ts │ │ ├── definePropsDestructure.ts │ │ ├── defineSlots.ts │ │ ├── importUsageCheck.ts │ │ ├── normalScript.ts │ │ ├── resolveType.ts │ │ ├── topLevelAwait.ts │ │ └── utils.ts │ │ ├── shims.d.ts │ │ ├── style │ │ ├── cssVars.ts │ │ ├── pluginScoped.ts │ │ ├── pluginTrim.ts │ │ └── preprocessors.ts │ │ ├── template │ │ ├── templateUtils.ts │ │ ├── transformAssetUrl.ts │ │ └── transformSrcset.ts │ │ └── warn.ts ├── compiler-ssr │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── ssrComponent.spec.ts │ │ ├── ssrElement.spec.ts │ │ ├── ssrFallthroughAttrs.spec.ts │ │ ├── ssrInjectCssVars.spec.ts │ │ ├── ssrPortal.spec.ts │ │ ├── ssrScopeId.spec.ts │ │ ├── ssrSlotOutlet.spec.ts │ │ ├── ssrSuspense.spec.ts │ │ ├── ssrText.spec.ts │ │ ├── ssrTransition.spec.ts │ │ ├── ssrTransitionGroup.spec.ts │ │ ├── ssrVFor.spec.ts │ │ ├── ssrVIf.spec.ts │ │ ├── ssrVModel.spec.ts │ │ ├── ssrVShow.spec.ts │ │ └── utils.ts │ ├── package.json │ └── src │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── runtimeHelpers.ts │ │ ├── ssrCodegenTransform.ts │ │ └── transforms │ │ ├── ssrInjectCssVars.ts │ │ ├── ssrInjectFallthroughAttrs.ts │ │ ├── ssrTransformComponent.ts │ │ ├── ssrTransformElement.ts │ │ ├── ssrTransformSlotOutlet.ts │ │ ├── ssrTransformSuspense.ts │ │ ├── ssrTransformTeleport.ts │ │ ├── ssrTransformTransition.ts │ │ ├── ssrTransformTransitionGroup.ts │ │ ├── ssrVFor.ts │ │ ├── ssrVIf.ts │ │ ├── ssrVModel.ts │ │ └── ssrVShow.ts ├── global.d.ts ├── reactivity │ ├── LICENSE │ ├── README.md │ ├── __benchmarks__ │ │ ├── computed.bench.ts │ │ ├── effect.bench.ts │ │ ├── reactiveArray.bench.ts │ │ ├── reactiveMap.bench.ts │ │ ├── reactiveObject.bench.ts │ │ └── ref.bench.ts │ ├── __tests__ │ │ ├── collections │ │ │ ├── Map.spec.ts │ │ │ ├── Set.spec.ts │ │ │ ├── WeakMap.spec.ts │ │ │ ├── WeakSet.spec.ts │ │ │ └── shallowReadonly.spec.ts │ │ ├── computed.spec.ts │ │ ├── effect.spec.ts │ │ ├── effectScope.spec.ts │ │ ├── gc.spec.ts │ │ ├── reactive.spec.ts │ │ ├── reactiveArray.spec.ts │ │ ├── readonly.spec.ts │ │ ├── ref.spec.ts │ │ ├── shallowReactive.spec.ts │ │ ├── shallowReadonly.spec.ts │ │ └── watch.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── arrayInstrumentations.ts │ │ ├── baseHandlers.ts │ │ ├── collectionHandlers.ts │ │ ├── computed.ts │ │ ├── constants.ts │ │ ├── dep.ts │ │ ├── effect.ts │ │ ├── effectScope.ts │ │ ├── index.ts │ │ ├── reactive.ts │ │ ├── ref.ts │ │ ├── warning.ts │ │ └── watch.ts ├── runtime-core │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── apiAsyncComponent.spec.ts │ │ ├── apiCreateApp.spec.ts │ │ ├── apiExpose.spec.ts │ │ ├── apiInject.spec.ts │ │ ├── apiLifecycle.spec.ts │ │ ├── apiOptions.spec.ts │ │ ├── apiSetupContext.spec.ts │ │ ├── apiSetupHelpers.spec.ts │ │ ├── apiWatch.bench.ts │ │ ├── apiWatch.spec.ts │ │ ├── componentEmits.spec.ts │ │ ├── componentProps.spec.ts │ │ ├── componentPublicInstance.spec.ts │ │ ├── componentSlots.spec.ts │ │ ├── components │ │ │ ├── BaseTransition.spec.ts │ │ │ ├── KeepAlive.spec.ts │ │ │ ├── Suspense.spec.ts │ │ │ └── Teleport.spec.ts │ │ ├── directives.spec.ts │ │ ├── errorHandling.spec.ts │ │ ├── h.spec.ts │ │ ├── helpers │ │ │ ├── createSlots.spec.ts │ │ │ ├── renderList.spec.ts │ │ │ ├── renderSlot.spec.ts │ │ │ ├── resolveAssets.spec.ts │ │ │ ├── toHandlers.spec.ts │ │ │ ├── useId.spec.ts │ │ │ ├── useModel.spec.ts │ │ │ ├── useTemplateRef.spec.ts │ │ │ └── withMemo.spec.ts │ │ ├── hmr.spec.ts │ │ ├── hydration.spec.ts │ │ ├── misc.spec.ts │ │ ├── rendererAttrsFallthrough.spec.ts │ │ ├── rendererChildren.spec.ts │ │ ├── rendererComponent.spec.ts │ │ ├── rendererElement.spec.ts │ │ ├── rendererFragment.spec.ts │ │ ├── rendererOptimizedMode.spec.ts │ │ ├── rendererTemplateRef.spec.ts │ │ ├── scheduler.spec.ts │ │ ├── scopeId.spec.ts │ │ ├── vnode.spec.ts │ │ └── vnodeHooks.spec.ts │ ├── index.js │ ├── package.json │ ├── src │ │ ├── apiAsyncComponent.ts │ │ ├── apiComputed.ts │ │ ├── apiCreateApp.ts │ │ ├── apiDefineComponent.ts │ │ ├── apiInject.ts │ │ ├── apiLifecycle.ts │ │ ├── apiSetupHelpers.ts │ │ ├── apiWatch.ts │ │ ├── compat │ │ │ ├── attrsFallthrough.ts │ │ │ ├── compatConfig.ts │ │ │ ├── component.ts │ │ │ ├── componentAsync.ts │ │ │ ├── componentFunctional.ts │ │ │ ├── componentVModel.ts │ │ │ ├── customDirective.ts │ │ │ ├── data.ts │ │ │ ├── global.ts │ │ │ ├── globalConfig.ts │ │ │ ├── instance.ts │ │ │ ├── instanceChildren.ts │ │ │ ├── instanceEventEmitter.ts │ │ │ ├── instanceListeners.ts │ │ │ ├── props.ts │ │ │ ├── renderFn.ts │ │ │ └── renderHelpers.ts │ │ ├── component.ts │ │ ├── componentEmits.ts │ │ ├── componentOptions.ts │ │ ├── componentProps.ts │ │ ├── componentPublicInstance.ts │ │ ├── componentRenderContext.ts │ │ ├── componentRenderUtils.ts │ │ ├── componentSlots.ts │ │ ├── components │ │ │ ├── BaseTransition.ts │ │ │ ├── KeepAlive.ts │ │ │ ├── Suspense.ts │ │ │ └── Teleport.ts │ │ ├── customFormatter.ts │ │ ├── devtools.ts │ │ ├── directives.ts │ │ ├── enums.ts │ │ ├── errorHandling.ts │ │ ├── featureFlags.ts │ │ ├── h.ts │ │ ├── helpers │ │ │ ├── createSlots.ts │ │ │ ├── renderList.ts │ │ │ ├── renderSlot.ts │ │ │ ├── resolveAssets.ts │ │ │ ├── toHandlers.ts │ │ │ ├── useId.ts │ │ │ ├── useModel.ts │ │ │ ├── useSsrContext.ts │ │ │ ├── useTemplateRef.ts │ │ │ └── withMemo.ts │ │ ├── hmr.ts │ │ ├── hydration.ts │ │ ├── hydrationStrategies.ts │ │ ├── index.ts │ │ ├── internalObject.ts │ │ ├── profiling.ts │ │ ├── renderer.ts │ │ ├── rendererTemplateRef.ts │ │ ├── scheduler.ts │ │ ├── vnode.ts │ │ └── warning.ts │ └── types │ │ ├── globalComponents.d.ts │ │ └── scriptSetupHelpers.d.ts ├── runtime-dom │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── createApp.spec.ts │ │ ├── customElement.spec.ts │ │ ├── customizedBuiltIn.spec.ts │ │ ├── directives │ │ │ ├── vCloak.spec.ts │ │ │ ├── vModel.spec.ts │ │ │ ├── vOn.spec.ts │ │ │ └── vShow.spec.ts │ │ ├── helpers │ │ │ ├── useCssModule.spec.ts │ │ │ └── useCssVars.spec.ts │ │ ├── nodeOps.spec.ts │ │ ├── patchAttrs.spec.ts │ │ ├── patchClass.spec.ts │ │ ├── patchEvents.spec.ts │ │ ├── patchProps.spec.ts │ │ ├── patchStyle.spec.ts │ │ └── rendererStaticNode.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── apiCustomElement.ts │ │ ├── components │ │ ├── Transition.ts │ │ └── TransitionGroup.ts │ │ ├── directives │ │ ├── vModel.ts │ │ ├── vOn.ts │ │ └── vShow.ts │ │ ├── helpers │ │ ├── useCssModule.ts │ │ └── useCssVars.ts │ │ ├── index.ts │ │ ├── jsx.ts │ │ ├── modules │ │ ├── attrs.ts │ │ ├── class.ts │ │ ├── events.ts │ │ ├── props.ts │ │ └── style.ts │ │ ├── nodeOps.ts │ │ └── patchProp.ts ├── runtime-test │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ └── testRuntime.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── nodeOps.ts │ │ ├── patchProp.ts │ │ ├── serialize.ts │ │ └── triggerEvent.ts ├── server-renderer │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── createBuffer.bench.ts │ │ ├── render.spec.ts │ │ ├── ssrAttrFallthrough.spec.ts │ │ ├── ssrCompilerOptions.spec.ts │ │ ├── ssrComputed.spec.ts │ │ ├── ssrDirectives.spec.ts │ │ ├── ssrDynamicComponent.spec.ts │ │ ├── ssrInterpolate.spec.ts │ │ ├── ssrRenderAttrs.spec.ts │ │ ├── ssrRenderList.spec.ts │ │ ├── ssrScopeId.spec.ts │ │ ├── ssrSlot.spec.ts │ │ ├── ssrSuspense.spec.ts │ │ ├── ssrTeleport.spec.ts │ │ ├── ssrVModelHelpers.spec.ts │ │ ├── ssrWatch.spec.ts │ │ ├── unrollBuffer.bench.ts │ │ └── webStream.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── helpers │ │ ├── ssrCompile.ts │ │ ├── ssrGetDirectiveProps.ts │ │ ├── ssrInterpolate.ts │ │ ├── ssrRenderAttrs.ts │ │ ├── ssrRenderComponent.ts │ │ ├── ssrRenderList.ts │ │ ├── ssrRenderSlot.ts │ │ ├── ssrRenderSuspense.ts │ │ ├── ssrRenderTeleport.ts │ │ └── ssrVModelHelpers.ts │ │ ├── index.ts │ │ ├── internal.ts │ │ ├── render.ts │ │ ├── renderToStream.ts │ │ └── renderToString.ts ├── shared │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── codeframe.spec.ts.snap │ │ ├── codeframe.spec.ts │ │ ├── escapeHtml.spec.ts │ │ ├── looseEqual.spec.ts │ │ ├── normalizeProp.spec.ts │ │ └── toDisplayString.spec.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── codeframe.ts │ │ ├── domAttrConfig.ts │ │ ├── domTagConfig.ts │ │ ├── escapeHtml.ts │ │ ├── general.ts │ │ ├── globalsAllowList.ts │ │ ├── index.ts │ │ ├── looseEqual.ts │ │ ├── makeMap.ts │ │ ├── normalizeProp.ts │ │ ├── patchFlags.ts │ │ ├── shapeFlags.ts │ │ ├── slotFlags.ts │ │ ├── toDisplayString.ts │ │ └── typeUtils.ts ├── vue-compat │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ │ ├── compiler.spec.ts │ │ ├── componentAsync.spec.ts │ │ ├── componentFunctional.spec.ts │ │ ├── componentVModel.spec.ts │ │ ├── filters.spec.ts │ │ ├── global.spec.ts │ │ ├── globalConfig.spec.ts │ │ ├── instance.spec.ts │ │ ├── misc.spec.ts │ │ ├── options.spec.ts │ │ ├── renderFn.spec.ts │ │ └── utils.ts │ ├── index.js │ ├── package.json │ └── src │ │ ├── createCompatVue.ts │ │ ├── dev.ts │ │ ├── esm-index.ts │ │ ├── esm-runtime.ts │ │ ├── index.ts │ │ └── runtime.ts └── vue │ ├── LICENSE │ ├── README.md │ ├── __tests__ │ ├── customElementCasing.spec.ts │ ├── e2e │ │ ├── Transition.spec.ts │ │ ├── TransitionGroup.spec.ts │ │ ├── commits.mock.ts │ │ ├── commits.spec.ts │ │ ├── e2eUtils.ts │ │ ├── grid.spec.ts │ │ ├── hydration-strat-custom.html │ │ ├── hydration-strat-idle.html │ │ ├── hydration-strat-interaction.html │ │ ├── hydration-strat-media.html │ │ ├── hydration-strat-visible.html │ │ ├── hydrationStrategies.spec.ts │ │ ├── markdown.spec.ts │ │ ├── ssr-custom-element.spec.ts │ │ ├── svg.spec.ts │ │ ├── todomvc.spec.ts │ │ ├── transition.html │ │ ├── tree.spec.ts │ │ ├── trusted-types.html │ │ ├── trusted-types.spec.ts │ │ └── vModel.spec.ts │ ├── index.spec.ts │ ├── mathmlNamespace.spec.ts │ ├── runtimeCompilerOptions.spec.ts │ └── svgNamespace.spec.ts │ ├── compiler-sfc │ ├── index.browser.js │ ├── index.browser.mjs │ ├── index.d.mts │ ├── index.d.ts │ ├── index.js │ ├── index.mjs │ ├── package.json │ └── register-ts.js │ ├── examples │ ├── classic │ │ ├── commits.html │ │ ├── grid.html │ │ ├── markdown.html │ │ ├── svg.html │ │ ├── todomvc.html │ │ └── tree.html │ ├── composition │ │ ├── commits.html │ │ ├── grid.html │ │ ├── markdown.html │ │ ├── svg.html │ │ ├── todomvc.html │ │ └── tree.html │ └── transition │ │ ├── list.html │ │ └── modal.html │ ├── index.js │ ├── index.mjs │ ├── jsx-runtime │ ├── index.d.ts │ ├── index.js │ ├── index.mjs │ └── package.json │ ├── jsx.d.ts │ ├── package.json │ ├── server-renderer │ ├── index.d.mts │ ├── index.d.ts │ ├── index.js │ ├── index.mjs │ └── package.json │ └── src │ ├── dev.ts │ ├── index.ts │ └── runtime.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── rollup.config.js ├── rollup.dts.config.js ├── scripts ├── aliases.js ├── build.js ├── dev.js ├── inline-enums.js ├── pre-dev-sfc.js ├── release.js ├── setup-vitest.ts ├── size-report.js ├── usage-size.js ├── utils.js ├── verify-commit.js └── verify-treeshaking.js ├── tsconfig.build.json ├── tsconfig.json ├── vitest.config.ts ├── vitest.e2e.config.ts ├── vitest.unit.config.ts └── vitest.workspace.ts /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # update prettier & eslint config (#9162) 2 | bfe6b459d3a0ce6168611ee1ac7e6e789709df9d 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: yyx990803 2 | open_collective: vuejs 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature Request 4 | url: https://github.com/vuejs/rfcs/discussions 5 | about: Suggest new features for consideration 6 | - name: Discord Chat 7 | url: https://chat.vuejs.org 8 | about: Ask questions and discuss with other Vue users in real time. 9 | - name: Questions & Discussions 10 | url: https://github.com/vuejs/core/discussions 11 | about: Use GitHub discussions for message-board style questions and discussions. 12 | - name: Patreon 13 | url: https://www.patreon.com/evanyou 14 | about: Love Vue.js? Please consider supporting us via Patreon. 15 | - name: Open Collective 16 | url: https://opencollective.com/vuejs/donate 17 | about: Love Vue.js? Please consider supporting us via Open Collective. 18 | -------------------------------------------------------------------------------- /.github/git-branch-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/core/e53a4ffbe0264b06971090fcaf0d8b2201478e29/.github/git-branch-workflow.png -------------------------------------------------------------------------------- /.github/issue-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/core/e53a4ffbe0264b06971090fcaf0d8b2201478e29/.github/issue-workflow.png -------------------------------------------------------------------------------- /.github/workflows/autofix.yml: -------------------------------------------------------------------------------- 1 | name: autofix.ci 2 | 3 | on: 4 | pull_request: 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | autofix: 10 | runs-on: ubuntu-latest 11 | env: 12 | PUPPETEER_SKIP_DOWNLOAD: 'true' 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Install pnpm 17 | uses: pnpm/action-setup@v4.1.0 18 | 19 | - name: Install Node.js 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version-file: '.node-version' 23 | registry-url: 'https://registry.npmjs.org' 24 | cache: 'pnpm' 25 | 26 | - run: pnpm install 27 | 28 | - name: Run eslint 29 | run: pnpm run lint --fix 30 | 31 | - name: Run prettier 32 | run: pnpm run format 33 | 34 | - uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef 35 | -------------------------------------------------------------------------------- /.github/workflows/canary-minor.yml: -------------------------------------------------------------------------------- 1 | name: canary minor release 2 | on: 3 | # Runs every Monday at 1 AM UTC (9:00 AM in Singapore) 4 | schedule: 5 | - cron: 0 1 * * MON 6 | workflow_dispatch: 7 | 8 | jobs: 9 | canary: 10 | # prevents this action from running on forks 11 | if: github.repository == 'vuejs/core' 12 | runs-on: ubuntu-latest 13 | environment: Release 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | ref: minor 18 | 19 | - name: Install pnpm 20 | uses: pnpm/action-setup@v4.1.0 21 | 22 | - name: Install Node.js 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version-file: '.node-version' 26 | registry-url: 'https://registry.npmjs.org' 27 | cache: 'pnpm' 28 | 29 | - run: pnpm install 30 | 31 | - run: pnpm release --canary --publish --tag minor 32 | env: 33 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 34 | -------------------------------------------------------------------------------- /.github/workflows/canary.yml: -------------------------------------------------------------------------------- 1 | name: canary release 2 | on: 3 | # Runs every Monday at 1 AM UTC (9:00 AM in Singapore) 4 | schedule: 5 | - cron: 0 1 * * MON 6 | workflow_dispatch: 7 | 8 | jobs: 9 | canary: 10 | # prevents this action from running on forks 11 | if: github.repository == 'vuejs/core' 12 | runs-on: ubuntu-latest 13 | environment: Release 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Install pnpm 18 | uses: pnpm/action-setup@v4.1.0 19 | 20 | - name: Install Node.js 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version-file: '.node-version' 24 | registry-url: 'https://registry.npmjs.org' 25 | cache: 'pnpm' 26 | 27 | - run: pnpm install 28 | 29 | - run: pnpm release --canary --publish 30 | env: 31 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: 'ci' 2 | on: 3 | push: 4 | branches: 5 | - '**' 6 | tags: 7 | - '!**' 8 | pull_request: 9 | branches: 10 | - main 11 | - minor 12 | 13 | jobs: 14 | test: 15 | if: ${{ ! startsWith(github.event.head_commit.message, 'release:') && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) }} 16 | uses: ./.github/workflows/test.yml 17 | 18 | continuous-release: 19 | if: github.repository == 'vuejs/core' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | 25 | - name: Install pnpm 26 | uses: pnpm/action-setup@v4 27 | 28 | - name: Install Node.js 29 | uses: actions/setup-node@v4 30 | with: 31 | node-version-file: '.node-version' 32 | registry-url: 'https://registry.npmjs.org' 33 | cache: 'pnpm' 34 | 35 | - name: Install deps 36 | run: pnpm install 37 | 38 | - name: Build 39 | run: pnpm build --withTypes 40 | 41 | - name: Release 42 | run: pnpx pkg-pr-new publish --compact --pnpm './packages/*' 43 | -------------------------------------------------------------------------------- /.github/workflows/close-cant-reproduce-issues.yml: -------------------------------------------------------------------------------- 1 | name: Auto close issues with "can't reproduce" label 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | permissions: 8 | issues: write 9 | 10 | jobs: 11 | close-issues: 12 | if: github.repository == 'vuejs/core' 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: can't reproduce 16 | uses: actions-cool/issues-helper@v3 17 | with: 18 | actions: 'close-issues' 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | labels: "can't reproduce" 21 | inactive-day: 3 22 | -------------------------------------------------------------------------------- /.github/workflows/lock-closed-issues.yml: -------------------------------------------------------------------------------- 1 | name: Lock Closed Issues 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | permissions: 8 | issues: write 9 | 10 | jobs: 11 | action: 12 | if: github.repository == 'vuejs/core' 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: dessant/lock-threads@v5 16 | with: 17 | github-token: ${{ secrets.GITHUB_TOKEN }} 18 | issue-inactive-days: '14' 19 | issue-lock-reason: '' 20 | process-only: 'issues' 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 7 | 8 | jobs: 9 | test: 10 | uses: ./.github/workflows/test.yml 11 | 12 | release: 13 | # prevents this action from running on forks 14 | if: github.repository == 'vuejs/core' 15 | needs: [test] 16 | runs-on: ubuntu-latest 17 | permissions: 18 | contents: write 19 | id-token: write 20 | # Use Release environment for deployment protection 21 | environment: Release 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Install pnpm 27 | uses: pnpm/action-setup@v4 28 | 29 | - name: Install Node.js 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version-file: '.node-version' 33 | registry-url: 'https://registry.npmjs.org' 34 | cache: 'pnpm' 35 | 36 | - name: Install deps 37 | run: pnpm install 38 | 39 | - name: Build and publish 40 | id: publish 41 | run: | 42 | pnpm release --publishOnly 43 | env: 44 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 45 | 46 | - name: Create GitHub release 47 | id: release_tag 48 | uses: yyx990803/release-tag@master 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | tag_name: ${{ github.ref }} 53 | body: | 54 | For stable releases, please refer to [CHANGELOG.md](https://github.com/vuejs/core/blob/main/CHANGELOG.md) for details. 55 | For pre-releases, please refer to [CHANGELOG.md](https://github.com/vuejs/core/blob/minor/CHANGELOG.md) of the `minor` branch. 56 | -------------------------------------------------------------------------------- /.github/workflows/size-data.yml: -------------------------------------------------------------------------------- 1 | name: size data 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - minor 8 | pull_request: 9 | branches: 10 | - main 11 | - minor 12 | 13 | permissions: 14 | contents: read 15 | 16 | env: 17 | PUPPETEER_SKIP_DOWNLOAD: 'true' 18 | 19 | jobs: 20 | upload: 21 | if: github.repository == 'vuejs/core' 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - name: Install pnpm 28 | uses: pnpm/action-setup@v4.1.0 29 | 30 | - name: Install Node.js 31 | uses: actions/setup-node@v4 32 | with: 33 | node-version-file: '.node-version' 34 | cache: pnpm 35 | 36 | - name: Install dependencies 37 | run: pnpm install 38 | 39 | - run: pnpm run size 40 | 41 | - name: Save PR number & base branch 42 | if: ${{github.event_name == 'pull_request'}} 43 | run: | 44 | echo ${{ github.event.number }} > ./temp/size/number.txt 45 | echo ${{ github.base_ref }} > ./temp/size/base.txt 46 | 47 | - name: Upload Size Data 48 | uses: actions/upload-artifact@v4 49 | with: 50 | name: size-data 51 | path: temp/size 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | .DS_Store 3 | node_modules 4 | coverage 5 | temp 6 | explorations 7 | TODOs.md 8 | *.log 9 | .idea 10 | .eslintcache 11 | dts-build/packages 12 | *.tsbuildinfo 13 | *.tgz 14 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 22.14.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | pnpm-lock.yaml 3 | CHANGELOG*.md 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "arrowParens": "avoid" 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["vitest.explorer"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Vitest - Debug Current Test File", 11 | "autoAttachChildProcesses": true, 12 | "skipFiles": ["/**", "**/node_modules/**"], 13 | "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs", 14 | "args": ["run", "${relativeFile}"], 15 | "smartStep": true, 16 | "console": "integratedTerminal" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use the project's typescript version 3 | "typescript.tsdk": "node_modules/typescript/lib", 4 | 5 | "cSpell.enabledLanguageIds": ["markdown", "plaintext", "text", "yml"], 6 | 7 | // Use prettier to format typescript, javascript and JSON files 8 | "[typescript]": { 9 | "editor.defaultFormatter": "esbenp.prettier-vscode" 10 | }, 11 | "[javascript]": { 12 | "editor.defaultFormatter": "esbenp.prettier-vscode" 13 | }, 14 | "[json]": { 15 | "editor.defaultFormatter": "esbenp.prettier-vscode" 16 | }, 17 | "editor.formatOnSave": true 18 | } 19 | -------------------------------------------------------------------------------- /.well-known/funding-manifest-urls: -------------------------------------------------------------------------------- 1 | https://vuejs.org/funding.json 2 | -------------------------------------------------------------------------------- /BACKERS.md: -------------------------------------------------------------------------------- 1 |

Sponsors & Backers

2 | 3 | Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of the awesome sponsors and backers listed in this file. If you'd like to join them, please consider [ sponsoring Vue's development](https://vuejs.org/sponsor/). 4 | 5 |

6 | 7 | sponsors 8 | 9 |

10 | -------------------------------------------------------------------------------- /FUNDING.json: -------------------------------------------------------------------------------- 1 | { 2 | "drips": { 3 | "ethereum": { 4 | "ownedBy": "0x5393BdeA2a020769256d9f337B0fc81a2F64850A" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You and Vue contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting a Vulnerability 2 | 3 | To report a vulnerability, please email security@vuejs.org. 4 | 5 | While the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Vue and its official companion libraries to ensure your application remains as secure as possible. 6 | 7 | Please note that we do not consider XSS via template expressions a valid attack vector, because it can only happen if the user intentionally uses untrusted content as template compilation source. This is similar to knowingly pasting untrusted scripts into a browser console. We explicitly warn users against using untrusted content as template compilation source in our documentation. 8 | 9 | ## Security Hall of Fame 10 | 11 | We would like to thank the following security researchers for responsibly disclosing security issues to us. 12 | 13 | - Jeet Pal - [@jeetpal2007](https://github.com/jeetpal2007) | [Email](mailto:jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290) 14 | - Mix - [@mnixry](https://github.com/mnixry) 15 | - Aviv Keller - [@RedYetiDev](https://github.com/redyetidev) | [LinkedIn](https://www.linkedin.com/in/redyetidev) 16 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build.environment] 2 | NODE_VERSION = "22" 3 | NPM_FLAGS = "--version" # prevent Netlify npm install 4 | -------------------------------------------------------------------------------- /packages-private/dts-built-test/README.md: -------------------------------------------------------------------------------- 1 | # dts built-package test 2 | 3 | This package is private and for testing only. It is used to verify edge cases for external libraries that build their types using Vue core types - e.g. Vuetify as in [#8376](https://github.com/vuejs/core/issues/8376). 4 | 5 | When running the `build-dts` task, this package's types are built alongside other packages. Then, during `test-dts-only` it is imported and used in [`packages-private/dts-test/built.test-d.ts`](https://github.com/vuejs/core/blob/main/packages-private/dts-test/built.test-d.ts) to verify that the built types work correctly. 6 | -------------------------------------------------------------------------------- /packages-private/dts-built-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dts-built-test", 3 | "private": true, 4 | "version": "0.0.0", 5 | "types": "dist/index.d.ts", 6 | "dependencies": { 7 | "@vue/shared": "workspace:*", 8 | "@vue/reactivity": "workspace:*", 9 | "vue": "workspace:*" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages-private/dts-built-test/src/index.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent } from 'vue' 2 | 3 | const _CustomPropsNotErased = defineComponent({ 4 | props: {}, 5 | setup() {}, 6 | }) 7 | 8 | // #8376 9 | export const CustomPropsNotErased = 10 | _CustomPropsNotErased as typeof _CustomPropsNotErased & { 11 | foo: string 12 | } 13 | -------------------------------------------------------------------------------- /packages-private/dts-built-test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "dist", 5 | "jsx": "preserve", 6 | "module": "esnext", 7 | "strict": true, 8 | "moduleResolution": "Bundler", 9 | "lib": ["esnext", "dom"], 10 | "declaration": true, 11 | "emitDeclarationOnly": true 12 | }, 13 | "include": ["./src"] 14 | } 15 | -------------------------------------------------------------------------------- /packages-private/dts-test/README.md: -------------------------------------------------------------------------------- 1 | # dts-test 2 | 3 | Tests TypeScript types to ensure the types remain as expected. 4 | 5 | - This directory is included in the root `tsconfig.json`, where package imports are aliased to `src` directories, so in IDEs and the `pnpm check` script the types are validated against source code. 6 | 7 | - When running `tsc` with `packages-private/dts-test/tsconfig.test.json`, packages are resolved using normal `node` resolution, so the types are validated against actual **built** types. This requires the types to be built first via `pnpm build-dts`. 8 | -------------------------------------------------------------------------------- /packages-private/dts-test/appDirective.test-d.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { expectType } from './utils' 3 | 4 | const app = createApp({}) 5 | 6 | app.directive( 7 | 'custom', 8 | { 9 | mounted(el, binding) { 10 | expectType(el) 11 | expectType(binding.value) 12 | expectType<{ prevent?: boolean; stop?: boolean }>(binding.modifiers) 13 | expectType<'arg1' | 'arg2'>(binding.arg!) 14 | 15 | // @ts-expect-error not any 16 | expectType(binding.value) 17 | }, 18 | }, 19 | ) 20 | -------------------------------------------------------------------------------- /packages-private/dts-test/built.test-d.ts: -------------------------------------------------------------------------------- 1 | import { CustomPropsNotErased } from 'dts-built-test/src/index' 2 | import { describe, expectType } from './utils' 3 | 4 | declare module 'vue' { 5 | interface ComponentCustomProps { 6 | custom?: number 7 | } 8 | } 9 | 10 | // #8376 - custom props should not be erased 11 | describe('Custom Props not erased', () => { 12 | expectType(new CustomPropsNotErased().$props.custom) 13 | }) 14 | -------------------------------------------------------------------------------- /packages-private/dts-test/compiler.test-d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Comment, 3 | Fragment, 4 | Static, 5 | Suspense, 6 | Teleport, 7 | Text, 8 | type VNode, 9 | createBlock, 10 | defineComponent, 11 | } from 'vue' 12 | import { expectType } from './utils' 13 | 14 | expectType(createBlock(Teleport)) 15 | expectType(createBlock(Text)) 16 | expectType(createBlock(Static)) 17 | expectType(createBlock(Comment)) 18 | expectType(createBlock(Fragment)) 19 | expectType(createBlock(Suspense)) 20 | expectType(createBlock(defineComponent({}))) 21 | -------------------------------------------------------------------------------- /packages-private/dts-test/directives.test-d.ts: -------------------------------------------------------------------------------- 1 | import { type Directive, type ObjectDirective, vModelText } from 'vue' 2 | import { describe, expectType } from './utils' 3 | 4 | type ExtractBinding = T extends ( 5 | el: any, 6 | binding: infer B, 7 | vnode: any, 8 | prev: any, 9 | ) => any 10 | ? B 11 | : never 12 | 13 | declare function testDirective< 14 | Value, 15 | Modifiers extends string = string, 16 | Arg extends string = string, 17 | >(): ExtractBinding> 18 | 19 | describe('vmodel', () => { 20 | expectType>( 21 | vModelText, 22 | ) 23 | // @ts-expect-error 24 | expectType>(vModelText) 25 | }) 26 | 27 | describe('custom', () => { 28 | expectType<{ 29 | value: number 30 | oldValue: number | null 31 | arg?: 'Arg' 32 | modifiers: Partial> 33 | }>(testDirective()) 34 | 35 | expectType<{ 36 | value: number 37 | oldValue: number | null 38 | arg?: 'Arg' 39 | modifiers: Record<'a' | 'b', boolean> 40 | // @ts-expect-error 41 | }>(testDirective()) 42 | 43 | expectType<{ 44 | value: number 45 | oldValue: number | null 46 | arg?: 'Arg' 47 | modifiers: Record<'a' | 'b', boolean> 48 | // @ts-expect-error 49 | }>(testDirective()) 50 | 51 | expectType<{ 52 | value: number 53 | oldValue: number | null 54 | arg?: 'Arg' 55 | modifiers: Record<'a' | 'b', boolean> 56 | // @ts-expect-error 57 | }>(testDirective()) 58 | }) 59 | -------------------------------------------------------------------------------- /packages-private/dts-test/extractProps.test-d.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, ExtractPublicPropTypes } from 'vue' 2 | import { type Prettify, expectType } from './utils' 3 | 4 | const propsOptions = { 5 | foo: { 6 | default: 1, 7 | }, 8 | bar: { 9 | type: String, 10 | required: true, 11 | }, 12 | baz: Boolean, 13 | qux: Array, 14 | } as const 15 | 16 | // internal facing props 17 | declare const props: Prettify> 18 | 19 | expectType(props.foo) 20 | expectType(props.bar) 21 | expectType(props.baz) 22 | expectType(props.qux) 23 | 24 | // external facing props 25 | declare const publicProps: Prettify> 26 | 27 | expectType(publicProps.foo) 28 | expectType(publicProps.bar) 29 | expectType(publicProps.baz) 30 | expectType(publicProps.qux) 31 | -------------------------------------------------------------------------------- /packages-private/dts-test/inject.test-d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type InjectionKey, 3 | type Ref, 4 | createApp, 5 | defineComponent, 6 | inject, 7 | provide, 8 | ref, 9 | } from 'vue' 10 | import { expectType } from './utils' 11 | 12 | // non-symbol keys 13 | provide('foo', 123) 14 | provide(123, 123) 15 | 16 | const key: InjectionKey = Symbol() 17 | 18 | provide(key, 1) 19 | // @ts-expect-error 20 | provide(key, 'foo') 21 | // @ts-expect-error 22 | provide(key, null) 23 | 24 | expectType(inject(key)) 25 | expectType(inject(key, 1)) 26 | expectType(inject(key, () => 1, true /* treatDefaultAsFactory */)) 27 | 28 | expectType<() => number>(inject('foo', () => 1)) 29 | expectType<() => number>(inject('foo', () => 1, false)) 30 | expectType(inject('foo', () => 1, true)) 31 | 32 | // #8201 33 | type Cube = { 34 | size: number 35 | } 36 | 37 | const injectionKeyRef = Symbol('key') as InjectionKey> 38 | 39 | // @ts-expect-error 40 | provide(injectionKeyRef, ref({})) 41 | 42 | // naive-ui: explicit provide type parameter 43 | provide('cube', { size: 123 }) 44 | provide(123, { size: 123 }) 45 | provide(injectionKeyRef, { size: 123 }) 46 | 47 | // @ts-expect-error 48 | provide('cube', { size: 'foo' }) 49 | // @ts-expect-error 50 | provide(123, { size: 'foo' }) 51 | 52 | // #10602 53 | const app = createApp({}) 54 | // @ts-expect-error 55 | app.provide(injectionKeyRef, ref({})) 56 | 57 | defineComponent({ 58 | provide: { 59 | [injectionKeyRef]: { size: 'foo' }, 60 | }, 61 | }) 62 | -------------------------------------------------------------------------------- /packages-private/dts-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dts-test", 3 | "private": true, 4 | "version": "0.0.0", 5 | "dependencies": { 6 | "vue": "workspace:*", 7 | "dts-built-test": "workspace:*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages-private/dts-test/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true, 4 | "jsx": "preserve", 5 | "module": "esnext", 6 | "strict": true, 7 | "moduleResolution": "node", 8 | "lib": ["esnext", "dom"] 9 | }, 10 | "include": ["./*"] 11 | } 12 | -------------------------------------------------------------------------------- /packages-private/dts-test/utils.d.ts: -------------------------------------------------------------------------------- 1 | // This directory contains a number of d.ts assertions 2 | // use \@ts-expect-error where errors are expected. 3 | 4 | // register global JSX 5 | import 'vue/jsx' 6 | 7 | export function describe(_name: string, _fn: () => void): void 8 | export function test(_name: string, _fn: () => any): void 9 | 10 | export function expectType(value: T): void 11 | export function expectAssignable(value: T2): void 12 | 13 | export type IsUnion = ( 14 | T extends any ? (U extends T ? false : true) : never 15 | ) extends false 16 | ? false 17 | : true 18 | 19 | export type IsAny = 0 extends 1 & T ? true : false 20 | 21 | export type Prettify = { [K in keyof T]: T[K] } & {} 22 | -------------------------------------------------------------------------------- /packages-private/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Global compile-time constants 4 | declare var __COMMIT__: string 5 | 6 | declare module 'file-saver' { 7 | export function saveAs(blob: any, name: any): void 8 | } 9 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/README.md: -------------------------------------------------------------------------------- 1 | # SFC Playground 2 | 3 | This is continuously deployed at [https://play.vuejs.org](https://play.vuejs.org). 4 | 5 | ## Run Locally in Dev 6 | 7 | In repo root: 8 | 9 | ```sh 10 | pnpm dev-sfc 11 | ``` 12 | 13 | ## Build for Prod 14 | 15 | In repo root 16 | 17 | ```sh 18 | pnpm build-sfc-playground 19 | ``` 20 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Vue SFC Playground 9 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/sfc-playground", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "serve": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "@vitejs/plugin-vue": "catalog:", 13 | "vite": "catalog:" 14 | }, 15 | "dependencies": { 16 | "@vue/repl": "^4.5.1", 17 | "file-saver": "^2.0.5", 18 | "jszip": "^3.10.1", 19 | "vue": "workspace:*" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/download/download.ts: -------------------------------------------------------------------------------- 1 | import { saveAs } from 'file-saver' 2 | 3 | import index from './template/index.html?raw' 4 | import main from './template/main.js?raw' 5 | import pkg from './template/package.json?raw' 6 | import config from './template/vite.config.js?raw' 7 | import readme from './template/README.md?raw' 8 | import type { ReplStore } from '@vue/repl' 9 | 10 | export async function downloadProject(store: ReplStore) { 11 | if (!confirm('Download project files?')) { 12 | return 13 | } 14 | 15 | const { default: JSZip } = await import('jszip') 16 | const zip = new JSZip() 17 | 18 | // basic structure 19 | zip.file('index.html', index) 20 | zip.file( 21 | 'package.json', 22 | pkg.replace(`"vue": "latest"`, `"vue": "${store.vueVersion || 'latest'}"`), 23 | ) 24 | zip.file('vite.config.js', config) 25 | zip.file('README.md', readme) 26 | 27 | // project src 28 | const src = zip.folder('src')! 29 | src.file('main.js', main) 30 | 31 | const files = store.getFiles() 32 | for (const file in files) { 33 | if (file !== 'import-map.json' && file !== 'tsconfig.json') { 34 | src.file(file, files[file]) 35 | } else { 36 | zip.file(file, files[file]) 37 | } 38 | } 39 | 40 | const blob = await zip.generateAsync({ type: 'blob' }) 41 | saveAs(blob, 'vue-project.zip') 42 | } 43 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/download/template/README.md: -------------------------------------------------------------------------------- 1 | # Vite Vue Starter 2 | 3 | This is a project template using [Vite](https://vitejs.dev/). It requires [Node.js](https://nodejs.org) version 18+ or 20+. 4 | 5 | To start: 6 | 7 | ```sh 8 | npm install 9 | npm run dev 10 | 11 | # if using yarn: 12 | yarn 13 | yarn dev 14 | 15 | # if using pnpm: 16 | pnpm install 17 | pnpm run dev 18 | ``` 19 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/download/template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/download/template/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/download/template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue-starter", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "serve": "vite preview" 9 | }, 10 | "dependencies": { 11 | "vue": "latest" 12 | }, 13 | "devDependencies": { 14 | "@vitejs/plugin-vue": "^5.2.4", 15 | "vite": "^6.3.5" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/download/template/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | }) 8 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/Copy.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/Download.vue: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/GitHub.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/Moon.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/Reload.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/Share.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/icons/Sun.vue: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | // @ts-expect-error Custom window property 5 | window.VUE_DEVTOOLS_CONFIG = { 6 | defaultSelectedAppId: 'repl', 7 | } 8 | 9 | createApp(App).mount('#app') 10 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/vue-dev-proxy-prod.ts: -------------------------------------------------------------------------------- 1 | // serve vue to the iframe sandbox during dev. 2 | export * from 'vue/dist/vue.runtime.esm-browser.prod.js' 3 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/vue-dev-proxy.ts: -------------------------------------------------------------------------------- 1 | // serve vue to the iframe sandbox during dev. 2 | export * from 'vue' 3 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/src/vue-server-renderer-dev-proxy.ts: -------------------------------------------------------------------------------- 1 | // serve vue/server-renderer to the iframe sandbox during dev. 2 | export * from 'vue/server-renderer' 3 | -------------------------------------------------------------------------------- /packages-private/sfc-playground/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "github": { 3 | "silent": true 4 | }, 5 | "headers": [ 6 | { 7 | "source": "/assets/(.*)", 8 | "headers": [ 9 | { 10 | "key": "Cache-Control", 11 | "value": "max-age=31536000, immutable" 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /packages-private/template-explorer/README.md: -------------------------------------------------------------------------------- 1 | ## Template Explorer 2 | 3 | Live explorer for template compilation output. 4 | 5 | To run: 6 | 7 | - `npm run dev-compiler` in repo root 8 | - When the compilation is done, in another terminal run `npm run open` 9 | 10 | Note: `index.html` uses CDN for dependencies and is continuously deployed at [https://template-explorer.vuejs.org](https://template-explorer.vuejs.org). For local development, use the scripts above. 11 | -------------------------------------------------------------------------------- /packages-private/template-explorer/_redirects: -------------------------------------------------------------------------------- 1 | https://vue-next-template-explorer.netlify.app https://template-explorer.vuejs.org 301! 2 | https://vue-next-template-explorer.netlify.app/* https://template-explorer.vuejs.org/:splat 301! 3 | -------------------------------------------------------------------------------- /packages-private/template-explorer/index.html: -------------------------------------------------------------------------------- 1 | Vue Template Explorer 2 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 21 | 22 | 25 | -------------------------------------------------------------------------------- /packages-private/template-explorer/local.html: -------------------------------------------------------------------------------- 1 | Vue Template Explorer 2 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 21 | 22 | 25 | -------------------------------------------------------------------------------- /packages-private/template-explorer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/template-explorer", 3 | "private": true, 4 | "version": "0.0.0", 5 | "buildOptions": { 6 | "formats": [ 7 | "global" 8 | ], 9 | "compat": true, 10 | "env": "development", 11 | "enableNonBrowserBranches": true 12 | }, 13 | "dependencies": { 14 | "monaco-editor": "^0.52.2", 15 | "source-map-js": "^1.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages-private/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "isolatedDeclarations": false 5 | }, 6 | "include": ["."] 7 | } 8 | -------------------------------------------------------------------------------- /packages-private/vite-debug/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /packages-private/vite-debug/README.md: -------------------------------------------------------------------------------- 1 | This package is used for debugging issues that are related to `@vitejs/plugin-vue`, or can only be reproduced in a Vite-based setup. It aims to be as close to production as possible so Vue packages are resolved to the dist files instead of source. 2 | -------------------------------------------------------------------------------- /packages-private/vite-debug/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /packages-private/vite-debug/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | const app = createApp(App) 5 | 6 | app.mount('#app') 7 | -------------------------------------------------------------------------------- /packages-private/vite-debug/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-debug", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "serve": "vite preview" 9 | }, 10 | "devDependencies": { 11 | "@vitejs/plugin-vue": "catalog:", 12 | "vite": "catalog:", 13 | "vue": "workspace:*" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages-private/vite-debug/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "moduleResolution": "bundler" 5 | }, 6 | "include": ["./*"] 7 | } 8 | -------------------------------------------------------------------------------- /packages-private/vite-debug/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | plugins: [vue()], 6 | }) 7 | -------------------------------------------------------------------------------- /packages/compiler-core/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/compiler-core/README.md: -------------------------------------------------------------------------------- 1 | # @vue/compiler-core 2 | -------------------------------------------------------------------------------- /packages/compiler-core/__tests__/scopeId.spec.ts: -------------------------------------------------------------------------------- 1 | import { baseCompile } from '../src/compile' 2 | 3 | /** 4 | * Ensure all slot functions are wrapped with _withCtx 5 | * which sets the currentRenderingInstance and currentScopeId when rendering 6 | * the slot. 7 | */ 8 | describe('scopeId compiler support', () => { 9 | test('should only work in module mode', () => { 10 | expect(() => { 11 | baseCompile(``, { scopeId: 'test' }) 12 | }).toThrow(`"scopeId" option is only supported in module mode`) 13 | }) 14 | 15 | test('should wrap default slot', () => { 16 | const { code } = baseCompile(`
`, { 17 | mode: 'module', 18 | scopeId: 'test', 19 | }) 20 | expect(code).toMatch(`default: _withCtx(() => [`) 21 | expect(code).toMatchSnapshot() 22 | }) 23 | 24 | test('should wrap named slots', () => { 25 | const { code } = baseCompile( 26 | ` 27 | 28 | 29 | 30 | `, 31 | { 32 | mode: 'module', 33 | scopeId: 'test', 34 | }, 35 | ) 36 | expect(code).toMatch(`foo: _withCtx(({ msg }) => [`) 37 | expect(code).toMatch(`bar: _withCtx(() => [`) 38 | expect(code).toMatchSnapshot() 39 | }) 40 | 41 | test('should wrap dynamic slots', () => { 42 | const { code } = baseCompile( 43 | ` 44 | 45 | 46 | 47 | `, 48 | { 49 | mode: 'module', 50 | scopeId: 'test', 51 | }, 52 | ) 53 | expect(code).toMatch(/name: "foo",\s+fn: _withCtx\(/) 54 | expect(code).toMatch(/name: i,\s+fn: _withCtx\(/) 55 | expect(code).toMatchSnapshot() 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /packages/compiler-core/__tests__/transforms/noopDirectiveTransform.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type ElementNode, 3 | type VNodeCall, 4 | noopDirectiveTransform, 5 | baseParse as parse, 6 | transform, 7 | } from '../../src' 8 | import { transformElement } from '../../src/transforms/transformElement' 9 | 10 | describe('compiler: noop directive transform', () => { 11 | test('should add no props to DOM', () => { 12 | const ast = parse(`
`) 13 | transform(ast, { 14 | nodeTransforms: [transformElement], 15 | directiveTransforms: { 16 | noop: noopDirectiveTransform, 17 | }, 18 | }) 19 | const node = ast.children[0] as ElementNode 20 | // As v-noop adds no properties the codegen should be identical to 21 | // rendering a div with no props or reactive data (so just the tag as the arg) 22 | expect((node.codegenNode as VNodeCall).props).toBeUndefined() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/compiler-core/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | if (process.env.NODE_ENV === 'production') { 4 | module.exports = require('./dist/compiler-core.cjs.prod.js') 5 | } else { 6 | module.exports = require('./dist/compiler-core.cjs.js') 7 | } 8 | -------------------------------------------------------------------------------- /packages/compiler-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/compiler-core", 3 | "version": "3.5.16", 4 | "description": "@vue/compiler-core", 5 | "main": "index.js", 6 | "module": "dist/compiler-core.esm-bundler.js", 7 | "types": "dist/compiler-core.d.ts", 8 | "files": [ 9 | "index.js", 10 | "dist" 11 | ], 12 | "exports": { 13 | ".": { 14 | "types": "./dist/compiler-core.d.ts", 15 | "node": { 16 | "production": "./dist/compiler-core.cjs.prod.js", 17 | "development": "./dist/compiler-core.cjs.js", 18 | "default": "./index.js" 19 | }, 20 | "module": "./dist/compiler-core.esm-bundler.js", 21 | "import": "./dist/compiler-core.esm-bundler.js", 22 | "require": "./index.js" 23 | }, 24 | "./*": "./*" 25 | }, 26 | "buildOptions": { 27 | "name": "VueCompilerCore", 28 | "compat": true, 29 | "formats": [ 30 | "esm-bundler", 31 | "cjs" 32 | ] 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/vuejs/core.git", 37 | "directory": "packages/compiler-core" 38 | }, 39 | "keywords": [ 40 | "vue" 41 | ], 42 | "author": "Evan You", 43 | "license": "MIT", 44 | "bugs": { 45 | "url": "https://github.com/vuejs/core/issues" 46 | }, 47 | "homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-core#readme", 48 | "dependencies": { 49 | "@babel/parser": "catalog:", 50 | "@vue/shared": "workspace:*", 51 | "entities": "^4.5.0", 52 | "estree-walker": "catalog:", 53 | "source-map-js": "catalog:" 54 | }, 55 | "devDependencies": { 56 | "@babel/types": "catalog:" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/compiler-core/src/transforms/noopDirectiveTransform.ts: -------------------------------------------------------------------------------- 1 | import type { DirectiveTransform } from '../transform' 2 | 3 | export const noopDirectiveTransform: DirectiveTransform = () => ({ props: [] }) 4 | -------------------------------------------------------------------------------- /packages/compiler-core/src/transforms/vMemo.ts: -------------------------------------------------------------------------------- 1 | import type { NodeTransform } from '../transform' 2 | import { findDir } from '../utils' 3 | import { 4 | ElementTypes, 5 | type MemoExpression, 6 | NodeTypes, 7 | type PlainElementNode, 8 | convertToBlock, 9 | createCallExpression, 10 | createFunctionExpression, 11 | } from '../ast' 12 | import { WITH_MEMO } from '../runtimeHelpers' 13 | 14 | const seen = new WeakSet() 15 | 16 | export const transformMemo: NodeTransform = (node, context) => { 17 | if (node.type === NodeTypes.ELEMENT) { 18 | const dir = findDir(node, 'memo') 19 | if (!dir || seen.has(node)) { 20 | return 21 | } 22 | seen.add(node) 23 | return () => { 24 | const codegenNode = 25 | node.codegenNode || 26 | (context.currentNode as PlainElementNode).codegenNode 27 | if (codegenNode && codegenNode.type === NodeTypes.VNODE_CALL) { 28 | // non-component sub tree should be turned into a block 29 | if (node.tagType !== ElementTypes.COMPONENT) { 30 | convertToBlock(codegenNode, context) 31 | } 32 | node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [ 33 | dir.exp!, 34 | createFunctionExpression(undefined, codegenNode), 35 | `_cache`, 36 | String(context.cached.length), 37 | ]) as MemoExpression 38 | // increment cache count 39 | context.cached.push(null) 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/compiler-core/src/transforms/vOnce.ts: -------------------------------------------------------------------------------- 1 | import type { NodeTransform } from '../transform' 2 | import { findDir } from '../utils' 3 | import { type ElementNode, type ForNode, type IfNode, NodeTypes } from '../ast' 4 | import { SET_BLOCK_TRACKING } from '../runtimeHelpers' 5 | 6 | const seen = new WeakSet() 7 | 8 | export const transformOnce: NodeTransform = (node, context) => { 9 | if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) { 10 | if (seen.has(node) || context.inVOnce || context.inSSR) { 11 | return 12 | } 13 | seen.add(node) 14 | context.inVOnce = true 15 | context.helper(SET_BLOCK_TRACKING) 16 | return () => { 17 | context.inVOnce = false 18 | const cur = context.currentNode as ElementNode | IfNode | ForNode 19 | if (cur.codegenNode) { 20 | cur.codegenNode = context.cache( 21 | cur.codegenNode, 22 | true /* isVNode */, 23 | true /* inVOnce */, 24 | ) 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/compiler-dom/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/compiler-dom/README.md: -------------------------------------------------------------------------------- 1 | # @vue/compiler-dom 2 | -------------------------------------------------------------------------------- /packages/compiler-dom/__tests__/__snapshots__/index.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`compile > should contain standard transforms 1`] = ` 4 | "const _Vue = Vue 5 | 6 | return function render(_ctx, _cache) { 7 | with (_ctx) { 8 | const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, normalizeStyle: _normalizeStyle, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue 9 | 10 | return (_openBlock(), _createElementBlock(_Fragment, null, [ 11 | _createElementVNode("div", { 12 | textContent: _toDisplayString(text) 13 | }, null, 8 /* PROPS */, ["textContent"]), 14 | _createElementVNode("div", { innerHTML: html }, null, 8 /* PROPS */, ["innerHTML"]), 15 | _createElementVNode("div", null, "test"), 16 | _createElementVNode("div", { style: {"color":"red"} }, "red"), 17 | _createElementVNode("div", { 18 | style: _normalizeStyle({color: 'green'}) 19 | }, null, 4 /* STYLE */) 20 | ], 64 /* STABLE_FRAGMENT */)) 21 | } 22 | }" 23 | `; 24 | -------------------------------------------------------------------------------- /packages/compiler-dom/__tests__/decoderHtmlBrowser.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @vitest-environment jsdom 3 | */ 4 | import { decodeHtmlBrowser } from '../src/decodeHtmlBrowser' 5 | 6 | describe('decodeHtmlBrowser', () => { 7 | it('should decode HTML correctly', () => { 8 | expect(decodeHtmlBrowser(' abc 123 ')).toBe(' abc 123 ') 9 | 10 | expect(decodeHtmlBrowser('&')).toBe('&') 11 | expect(decodeHtmlBrowser('&')).toBe('&') 12 | expect(decodeHtmlBrowser('&amp;')).toBe('&') 13 | 14 | expect(decodeHtmlBrowser('<')).toBe('<') 15 | expect(decodeHtmlBrowser('<')).toBe('<') 16 | expect(decodeHtmlBrowser('&lt;')).toBe('<') 17 | 18 | expect(decodeHtmlBrowser('>')).toBe('>') 19 | expect(decodeHtmlBrowser('>')).toBe('>') 20 | expect(decodeHtmlBrowser('&gt;')).toBe('>') 21 | 22 | expect(decodeHtmlBrowser(' ')).toBe('\u00a0') 23 | expect(decodeHtmlBrowser('"')).toBe('"') 24 | expect(decodeHtmlBrowser(''')).toBe("'") 25 | 26 | expect(decodeHtmlBrowser('É')).toBe('\u00c9') 27 | expect(decodeHtmlBrowser('É')).toBe('\u00c9') 28 | expect(decodeHtmlBrowser('É')).toBe('\u00c9') 29 | 30 | // #3001 html tags inside attribute values 31 | expect(decodeHtmlBrowser('Text', true)).toBe( 32 | 'Text', 33 | ) 34 | expect(decodeHtmlBrowser('&', true)).toBe( 35 | '&', 36 | ) 37 | expect( 38 | decodeHtmlBrowser( 39 | '<strong>&</strong>', 40 | true, 41 | ), 42 | ).toBe('&') 43 | expect(decodeHtmlBrowser('"', true)).toBe('"') 44 | expect(decodeHtmlBrowser("'", true)).toBe("'") 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /packages/compiler-dom/__tests__/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { compile } from '../src' 2 | 3 | describe('compile', () => { 4 | it('should contain standard transforms', () => { 5 | const { code } = compile(`
6 |
7 |
test
8 |
red
9 |
`) 10 | 11 | expect(code).toMatchSnapshot() 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/compiler-dom/__tests__/transforms/__snapshots__/vShow.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`compiler: v-show transform > simple expression 1`] = ` 4 | "const _Vue = Vue 5 | 6 | return function render(_ctx, _cache) { 7 | with (_ctx) { 8 | const { vShow: _vShow, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue 9 | 10 | return _withDirectives((_openBlock(), _createElementBlock("div", null, null, 512 /* NEED_PATCH */)), [ 11 | [_vShow, a] 12 | ]) 13 | } 14 | }" 15 | `; 16 | -------------------------------------------------------------------------------- /packages/compiler-dom/__tests__/transforms/ignoreSideEffectTags.spec.ts: -------------------------------------------------------------------------------- 1 | import { type CompilerError, compile } from '../../src' 2 | 3 | describe('compiler: ignore side effect tags', () => { 4 | it('should ignore script', () => { 5 | let err: CompilerError | undefined 6 | const { code } = compile(``, { 7 | onError(e) { 8 | err = e 9 | }, 10 | }) 11 | expect(code).not.toMatch('script') 12 | expect(err).toBeDefined() 13 | expect(err!.message).toMatch(`Tags with side effect`) 14 | }) 15 | 16 | it('should ignore style', () => { 17 | let err: CompilerError | undefined 18 | const { code } = compile(``, { 19 | onError(e) { 20 | err = e 21 | }, 22 | }) 23 | expect(code).not.toMatch('style') 24 | expect(err).toBeDefined() 25 | expect(err!.message).toMatch(`Tags with side effect`) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /packages/compiler-dom/__tests__/transforms/vShow.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type CompilerOptions, 3 | generate, 4 | baseParse as parse, 5 | transform, 6 | } from '@vue/compiler-core' 7 | import { transformElement } from '../../../compiler-core/src/transforms/transformElement' 8 | import { transformShow } from '../../src/transforms/vShow' 9 | import { DOMErrorCodes } from '../../src/errors' 10 | 11 | function transformWithShow(template: string, options: CompilerOptions = {}) { 12 | const ast = parse(template) 13 | transform(ast, { 14 | nodeTransforms: [transformElement], 15 | directiveTransforms: { 16 | show: transformShow, 17 | }, 18 | ...options, 19 | }) 20 | return ast 21 | } 22 | 23 | describe('compiler: v-show transform', () => { 24 | test('simple expression', () => { 25 | const ast = transformWithShow(`
`) 26 | 27 | expect(generate(ast).code).toMatchSnapshot() 28 | }) 29 | 30 | test('should raise error if has no expression', () => { 31 | const onError = vi.fn() 32 | transformWithShow(`
`, { onError }) 33 | 34 | expect(onError).toHaveBeenCalledTimes(1) 35 | expect(onError).toHaveBeenCalledWith( 36 | expect.objectContaining({ 37 | code: DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, 38 | }), 39 | ) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /packages/compiler-dom/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | if (process.env.NODE_ENV === 'production') { 4 | module.exports = require('./dist/compiler-dom.cjs.prod.js') 5 | } else { 6 | module.exports = require('./dist/compiler-dom.cjs.js') 7 | } 8 | -------------------------------------------------------------------------------- /packages/compiler-dom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/compiler-dom", 3 | "version": "3.5.16", 4 | "description": "@vue/compiler-dom", 5 | "main": "index.js", 6 | "module": "dist/compiler-dom.esm-bundler.js", 7 | "types": "dist/compiler-dom.d.ts", 8 | "unpkg": "dist/compiler-dom.global.js", 9 | "jsdelivr": "dist/compiler-dom.global.js", 10 | "files": [ 11 | "index.js", 12 | "dist" 13 | ], 14 | "exports": { 15 | ".": { 16 | "types": "./dist/compiler-dom.d.ts", 17 | "node": { 18 | "production": "./dist/compiler-dom.cjs.prod.js", 19 | "development": "./dist/compiler-dom.cjs.js", 20 | "default": "./index.js" 21 | }, 22 | "module": "./dist/compiler-dom.esm-bundler.js", 23 | "import": "./dist/compiler-dom.esm-bundler.js", 24 | "require": "./index.js" 25 | }, 26 | "./*": "./*" 27 | }, 28 | "sideEffects": false, 29 | "buildOptions": { 30 | "name": "VueCompilerDOM", 31 | "compat": true, 32 | "formats": [ 33 | "esm-bundler", 34 | "esm-browser", 35 | "cjs", 36 | "global" 37 | ] 38 | }, 39 | "repository": { 40 | "type": "git", 41 | "url": "git+https://github.com/vuejs/core.git", 42 | "directory": "packages/compiler-dom" 43 | }, 44 | "keywords": [ 45 | "vue" 46 | ], 47 | "author": "Evan You", 48 | "license": "MIT", 49 | "bugs": { 50 | "url": "https://github.com/vuejs/core/issues" 51 | }, 52 | "homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-dom#readme", 53 | "dependencies": { 54 | "@vue/shared": "workspace:*", 55 | "@vue/compiler-core": "workspace:*" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/decodeHtmlBrowser.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-globals */ 2 | 3 | let decoder: HTMLDivElement 4 | 5 | export function decodeHtmlBrowser(raw: string, asAttr = false): string { 6 | if (!decoder) { 7 | decoder = document.createElement('div') 8 | } 9 | if (asAttr) { 10 | decoder.innerHTML = `
` 11 | return decoder.children[0].getAttribute('foo')! 12 | } else { 13 | decoder.innerHTML = raw 14 | return decoder.textContent! 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/runtimeHelpers.ts: -------------------------------------------------------------------------------- 1 | import { registerRuntimeHelpers } from '@vue/compiler-core' 2 | 3 | export const V_MODEL_RADIO: unique symbol = Symbol(__DEV__ ? `vModelRadio` : ``) 4 | export const V_MODEL_CHECKBOX: unique symbol = Symbol( 5 | __DEV__ ? `vModelCheckbox` : ``, 6 | ) 7 | export const V_MODEL_TEXT: unique symbol = Symbol(__DEV__ ? `vModelText` : ``) 8 | export const V_MODEL_SELECT: unique symbol = Symbol( 9 | __DEV__ ? `vModelSelect` : ``, 10 | ) 11 | export const V_MODEL_DYNAMIC: unique symbol = Symbol( 12 | __DEV__ ? `vModelDynamic` : ``, 13 | ) 14 | 15 | export const V_ON_WITH_MODIFIERS: unique symbol = Symbol( 16 | __DEV__ ? `vOnModifiersGuard` : ``, 17 | ) 18 | export const V_ON_WITH_KEYS: unique symbol = Symbol( 19 | __DEV__ ? `vOnKeysGuard` : ``, 20 | ) 21 | 22 | export const V_SHOW: unique symbol = Symbol(__DEV__ ? `vShow` : ``) 23 | 24 | export const TRANSITION: unique symbol = Symbol(__DEV__ ? `Transition` : ``) 25 | export const TRANSITION_GROUP: unique symbol = Symbol( 26 | __DEV__ ? `TransitionGroup` : ``, 27 | ) 28 | 29 | registerRuntimeHelpers({ 30 | [V_MODEL_RADIO]: `vModelRadio`, 31 | [V_MODEL_CHECKBOX]: `vModelCheckbox`, 32 | [V_MODEL_TEXT]: `vModelText`, 33 | [V_MODEL_SELECT]: `vModelSelect`, 34 | [V_MODEL_DYNAMIC]: `vModelDynamic`, 35 | [V_ON_WITH_MODIFIERS]: `withModifiers`, 36 | [V_ON_WITH_KEYS]: `withKeys`, 37 | [V_SHOW]: `vShow`, 38 | [TRANSITION]: `Transition`, 39 | [TRANSITION_GROUP]: `TransitionGroup`, 40 | }) 41 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/transforms/ignoreSideEffectTags.ts: -------------------------------------------------------------------------------- 1 | import { ElementTypes, type NodeTransform, NodeTypes } from '@vue/compiler-core' 2 | import { DOMErrorCodes, createDOMCompilerError } from '../errors' 3 | 4 | export const ignoreSideEffectTags: NodeTransform = (node, context) => { 5 | if ( 6 | node.type === NodeTypes.ELEMENT && 7 | node.tagType === ElementTypes.ELEMENT && 8 | (node.tag === 'script' || node.tag === 'style') 9 | ) { 10 | __DEV__ && 11 | context.onError( 12 | createDOMCompilerError( 13 | DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG, 14 | node.loc, 15 | ), 16 | ) 17 | context.removeNode() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/transforms/transformStyle.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ConstantTypes, 3 | type NodeTransform, 4 | NodeTypes, 5 | type SimpleExpressionNode, 6 | type SourceLocation, 7 | createSimpleExpression, 8 | } from '@vue/compiler-core' 9 | import { parseStringStyle } from '@vue/shared' 10 | 11 | // Parse inline CSS strings for static style attributes into an object. 12 | // This is a NodeTransform since it works on the static `style` attribute and 13 | // converts it into a dynamic equivalent: 14 | // style="color: red" -> :style='{ "color": "red" }' 15 | // It is then processed by `transformElement` and included in the generated 16 | // props. 17 | export const transformStyle: NodeTransform = node => { 18 | if (node.type === NodeTypes.ELEMENT) { 19 | node.props.forEach((p, i) => { 20 | if (p.type === NodeTypes.ATTRIBUTE && p.name === 'style' && p.value) { 21 | // replace p with an expression node 22 | node.props[i] = { 23 | type: NodeTypes.DIRECTIVE, 24 | name: `bind`, 25 | arg: createSimpleExpression(`style`, true, p.loc), 26 | exp: parseInlineCSS(p.value.content, p.loc), 27 | modifiers: [], 28 | loc: p.loc, 29 | } 30 | } 31 | }) 32 | } 33 | } 34 | 35 | const parseInlineCSS = ( 36 | cssText: string, 37 | loc: SourceLocation, 38 | ): SimpleExpressionNode => { 39 | const normalized = parseStringStyle(cssText) 40 | return createSimpleExpression( 41 | JSON.stringify(normalized), 42 | false, 43 | loc, 44 | ConstantTypes.CAN_STRINGIFY, 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/transforms/vHtml.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type DirectiveTransform, 3 | createObjectProperty, 4 | createSimpleExpression, 5 | } from '@vue/compiler-core' 6 | import { DOMErrorCodes, createDOMCompilerError } from '../errors' 7 | 8 | export const transformVHtml: DirectiveTransform = (dir, node, context) => { 9 | const { exp, loc } = dir 10 | if (!exp) { 11 | context.onError( 12 | createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc), 13 | ) 14 | } 15 | if (node.children.length) { 16 | context.onError( 17 | createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc), 18 | ) 19 | node.children.length = 0 20 | } 21 | return { 22 | props: [ 23 | createObjectProperty( 24 | createSimpleExpression(`innerHTML`, true, loc), 25 | exp || createSimpleExpression('', true), 26 | ), 27 | ], 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/transforms/vShow.ts: -------------------------------------------------------------------------------- 1 | import type { DirectiveTransform } from '@vue/compiler-core' 2 | import { DOMErrorCodes, createDOMCompilerError } from '../errors' 3 | import { V_SHOW } from '../runtimeHelpers' 4 | 5 | export const transformShow: DirectiveTransform = (dir, node, context) => { 6 | const { exp, loc } = dir 7 | if (!exp) { 8 | context.onError( 9 | createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc), 10 | ) 11 | } 12 | 13 | return { 14 | props: [], 15 | needRuntime: context.helper(V_SHOW), 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/transforms/vText.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type DirectiveTransform, 3 | TO_DISPLAY_STRING, 4 | createCallExpression, 5 | createObjectProperty, 6 | createSimpleExpression, 7 | getConstantType, 8 | } from '@vue/compiler-core' 9 | import { DOMErrorCodes, createDOMCompilerError } from '../errors' 10 | 11 | export const transformVText: DirectiveTransform = (dir, node, context) => { 12 | const { exp, loc } = dir 13 | if (!exp) { 14 | context.onError( 15 | createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc), 16 | ) 17 | } 18 | if (node.children.length) { 19 | context.onError( 20 | createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc), 21 | ) 22 | node.children.length = 0 23 | } 24 | return { 25 | props: [ 26 | createObjectProperty( 27 | createSimpleExpression(`textContent`, true), 28 | exp 29 | ? getConstantType(exp, context) > 0 30 | ? exp 31 | : createCallExpression( 32 | context.helperString(TO_DISPLAY_STRING), 33 | [exp], 34 | loc, 35 | ) 36 | : createSimpleExpression('', true), 37 | ), 38 | ], 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/compiler-dom/src/transforms/validateHtmlNesting.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type CompilerError, 3 | ElementTypes, 4 | type NodeTransform, 5 | NodeTypes, 6 | } from '@vue/compiler-core' 7 | import { isValidHTMLNesting } from '../htmlNesting' 8 | 9 | export const validateHtmlNesting: NodeTransform = (node, context) => { 10 | if ( 11 | node.type === NodeTypes.ELEMENT && 12 | node.tagType === ElementTypes.ELEMENT && 13 | context.parent && 14 | context.parent.type === NodeTypes.ELEMENT && 15 | context.parent.tagType === ElementTypes.ELEMENT && 16 | !isValidHTMLNesting(context.parent.tag, node.tag) 17 | ) { 18 | const error = new SyntaxError( 19 | `<${node.tag}> cannot be child of <${context.parent.tag}>, ` + 20 | 'according to HTML specifications. ' + 21 | 'This can cause hydration errors or ' + 22 | 'potentially disrupt future functionality.', 23 | ) as CompilerError 24 | error.loc = node.loc 25 | context.onWarn(error) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/compiler-sfc/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineExpose.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[` 8 | `) 9 | assertCode(content) 10 | // should remove defineOptions import and call 11 | expect(content).not.toMatch('defineExpose') 12 | // should generate correct setup signature 13 | expect(content).toMatch(`setup(__props, { expose: __expose }) {`) 14 | // should replace callee 15 | expect(content).toMatch(/\b__expose\(\{ foo: 123 \}\)/) 16 | }) 17 | 18 | test(' 23 | 24 | `) 25 | assertCode(content) 26 | }) 27 | -------------------------------------------------------------------------------- /packages/compiler-sfc/__tests__/compileScript/defineSlots.spec.ts: -------------------------------------------------------------------------------- 1 | import { assertCode, compileSFCScript as compile } from '../utils' 2 | 3 | describe('defineSlots()', () => { 4 | test('basic usage', () => { 5 | const { content } = compile(` 6 | 11 | `) 12 | assertCode(content) 13 | expect(content).toMatch(`const slots = _useSlots()`) 14 | expect(content).not.toMatch('defineSlots') 15 | }) 16 | 17 | test('w/o return value', () => { 18 | const { content } = compile(` 19 | 24 | `) 25 | assertCode(content) 26 | expect(content).not.toMatch('defineSlots') 27 | expect(content).not.toMatch(`_useSlots`) 28 | }) 29 | 30 | test('w/o generic params', () => { 31 | const { content } = compile(` 32 | 35 | `) 36 | assertCode(content) 37 | expect(content).toMatch(`const slots = _useSlots()`) 38 | expect(content).not.toMatch('defineSlots') 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /packages/compiler-sfc/__tests__/fixture/import.scss: -------------------------------------------------------------------------------- 1 | div { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/cache.ts: -------------------------------------------------------------------------------- 1 | import { LRUCache } from 'lru-cache' 2 | 3 | export function createCache( 4 | max = 500, 5 | ): Map | LRUCache { 6 | /* v8 ignore next 3 */ 7 | if (__GLOBAL__ || __ESM_BROWSER__) { 8 | return new Map() 9 | } 10 | return new LRUCache({ max }) 11 | } 12 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/script/defineExpose.ts: -------------------------------------------------------------------------------- 1 | import type { Node } from '@babel/types' 2 | import { isCallOf } from './utils' 3 | import type { ScriptCompileContext } from './context' 4 | 5 | export const DEFINE_EXPOSE = 'defineExpose' 6 | 7 | export function processDefineExpose( 8 | ctx: ScriptCompileContext, 9 | node: Node, 10 | ): boolean { 11 | if (isCallOf(node, DEFINE_EXPOSE)) { 12 | if (ctx.hasDefineExposeCall) { 13 | ctx.error(`duplicate ${DEFINE_EXPOSE}() call`, node) 14 | } 15 | ctx.hasDefineExposeCall = true 16 | return true 17 | } 18 | return false 19 | } 20 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/script/defineSlots.ts: -------------------------------------------------------------------------------- 1 | import type { LVal, Node } from '@babel/types' 2 | import { isCallOf } from './utils' 3 | import type { ScriptCompileContext } from './context' 4 | 5 | export const DEFINE_SLOTS = 'defineSlots' 6 | 7 | export function processDefineSlots( 8 | ctx: ScriptCompileContext, 9 | node: Node, 10 | declId?: LVal, 11 | ): boolean { 12 | if (!isCallOf(node, DEFINE_SLOTS)) { 13 | return false 14 | } 15 | if (ctx.hasDefineSlotsCall) { 16 | ctx.error(`duplicate ${DEFINE_SLOTS}() call`, node) 17 | } 18 | ctx.hasDefineSlotsCall = true 19 | 20 | if (node.arguments.length > 0) { 21 | ctx.error(`${DEFINE_SLOTS}() cannot accept arguments`, node) 22 | } 23 | 24 | if (declId) { 25 | ctx.s.overwrite( 26 | ctx.startOffset! + node.start!, 27 | ctx.startOffset! + node.end!, 28 | `${ctx.helper('useSlots')}()`, 29 | ) 30 | } 31 | 32 | return true 33 | } 34 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/shims.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'merge-source-map' { 2 | export default function merge(oldMap: object, newMap: object): object 3 | } 4 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/style/pluginTrim.ts: -------------------------------------------------------------------------------- 1 | import type { PluginCreator } from 'postcss' 2 | 3 | const trimPlugin: PluginCreator<{}> = () => { 4 | return { 5 | postcssPlugin: 'vue-sfc-trim', 6 | Once(root) { 7 | root.walk(({ type, raws }) => { 8 | if (type === 'rule' || type === 'atrule') { 9 | if (raws.before) raws.before = '\n' 10 | if ('after' in raws && raws.after) raws.after = '\n' 11 | } 12 | }) 13 | }, 14 | } 15 | } 16 | 17 | trimPlugin.postcss = true 18 | export default trimPlugin 19 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/template/templateUtils.ts: -------------------------------------------------------------------------------- 1 | import { type UrlWithStringQuery, parse as uriParse } from 'url' 2 | import { isString } from '@vue/shared' 3 | 4 | export function isRelativeUrl(url: string): boolean { 5 | const firstChar = url.charAt(0) 6 | return firstChar === '.' || firstChar === '~' || firstChar === '@' 7 | } 8 | 9 | const externalRE = /^(https?:)?\/\// 10 | export function isExternalUrl(url: string): boolean { 11 | return externalRE.test(url) 12 | } 13 | 14 | const dataUrlRE = /^\s*data:/i 15 | export function isDataUrl(url: string): boolean { 16 | return dataUrlRE.test(url) 17 | } 18 | 19 | /** 20 | * Parses string url into URL object. 21 | */ 22 | export function parseUrl(url: string): UrlWithStringQuery { 23 | const firstChar = url.charAt(0) 24 | if (firstChar === '~') { 25 | const secondChar = url.charAt(1) 26 | url = url.slice(secondChar === '/' ? 2 : 1) 27 | } 28 | return parseUriParts(url) 29 | } 30 | 31 | /** 32 | * vuejs/component-compiler-utils#22 Support uri fragment in transformed require 33 | * @param urlString - an url as a string 34 | */ 35 | function parseUriParts(urlString: string): UrlWithStringQuery { 36 | // A TypeError is thrown if urlString is not a string 37 | // @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost 38 | return uriParse(isString(urlString) ? urlString : '', false, true) 39 | } 40 | -------------------------------------------------------------------------------- /packages/compiler-sfc/src/warn.ts: -------------------------------------------------------------------------------- 1 | const hasWarned: Record = {} 2 | 3 | export function warnOnce(msg: string): void { 4 | const isNodeProd = 5 | typeof process !== 'undefined' && process.env.NODE_ENV === 'production' 6 | if (!isNodeProd && !__TEST__ && !hasWarned[msg]) { 7 | hasWarned[msg] = true 8 | warn(msg) 9 | } 10 | } 11 | 12 | export function warn(msg: string): void { 13 | console.warn( 14 | `\x1b[1m\x1b[33m[@vue/compiler-sfc]\x1b[0m\x1b[33m ${msg}\x1b[0m\n`, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /packages/compiler-ssr/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/compiler-ssr/README.md: -------------------------------------------------------------------------------- 1 | # @vue/compiler-ssr 2 | -------------------------------------------------------------------------------- /packages/compiler-ssr/__tests__/ssrPortal.spec.ts: -------------------------------------------------------------------------------- 1 | import { compile } from '../src' 2 | 3 | describe('ssr compile: teleport', () => { 4 | test('should work', () => { 5 | expect(compile(`
`).code) 6 | .toMatchInlineSnapshot(` 7 | "const { ssrRenderTeleport: _ssrRenderTeleport } = require("vue/server-renderer") 8 | 9 | return function ssrRender(_ctx, _push, _parent, _attrs) { 10 | _ssrRenderTeleport(_push, (_push) => { 11 | _push(\`
\`) 12 | }, _ctx.target, false, _parent) 13 | }" 14 | `) 15 | }) 16 | 17 | test('disabled prop handling', () => { 18 | expect(compile(`
`).code) 19 | .toMatchInlineSnapshot(` 20 | "const { ssrRenderTeleport: _ssrRenderTeleport } = require("vue/server-renderer") 21 | 22 | return function ssrRender(_ctx, _push, _parent, _attrs) { 23 | _ssrRenderTeleport(_push, (_push) => { 24 | _push(\`
\`) 25 | }, _ctx.target, true, _parent) 26 | }" 27 | `) 28 | 29 | expect( 30 | compile(`
`).code, 31 | ).toMatchInlineSnapshot(` 32 | "const { ssrRenderTeleport: _ssrRenderTeleport } = require("vue/server-renderer") 33 | 34 | return function ssrRender(_ctx, _push, _parent, _attrs) { 35 | _ssrRenderTeleport(_push, (_push) => { 36 | _push(\`
\`) 37 | }, _ctx.target, _ctx.foo, _parent) 38 | }" 39 | `) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /packages/compiler-ssr/__tests__/ssrTransition.spec.ts: -------------------------------------------------------------------------------- 1 | import { compile } from '../src' 2 | 3 | describe('transition', () => { 4 | test('basic', () => { 5 | expect(compile(`
foo
`).code) 6 | .toMatchInlineSnapshot(` 7 | "const { ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer") 8 | 9 | return function ssrRender(_ctx, _push, _parent, _attrs) { 10 | _push(\`foo
\`) 11 | }" 12 | `) 13 | }) 14 | 15 | test('with appear', () => { 16 | expect(compile(`
foo
`).code) 17 | .toMatchInlineSnapshot(` 18 | "const { ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer") 19 | 20 | return function ssrRender(_ctx, _push, _parent, _attrs) { 21 | _push(\`\`) 22 | }" 23 | `) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /packages/compiler-ssr/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import { compile } from '../src' 2 | 3 | export function getCompiledString(src: string): string { 4 | // Wrap src template in a root div so that it doesn't get injected 5 | // fallthrough attr. This results in less noise in generated snapshots 6 | // but also means this util can only be used for non-root cases. 7 | const { code } = compile(`
${src}
`) 8 | const match = code.match( 9 | /_push\(\`([^]*)<\/div>\`\)/, 10 | ) 11 | 12 | if (!match) { 13 | throw new Error(`Unexpected compile result:\n${code}`) 14 | } 15 | 16 | return `\`${match[1]}\`` 17 | } 18 | -------------------------------------------------------------------------------- /packages/compiler-ssr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/compiler-ssr", 3 | "version": "3.5.16", 4 | "description": "@vue/compiler-ssr", 5 | "main": "dist/compiler-ssr.cjs.js", 6 | "types": "dist/compiler-ssr.d.ts", 7 | "files": [ 8 | "dist" 9 | ], 10 | "buildOptions": { 11 | "prod": false, 12 | "formats": [ 13 | "cjs" 14 | ] 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/vuejs/core.git", 19 | "directory": "packages/compiler-ssr" 20 | }, 21 | "keywords": [ 22 | "vue" 23 | ], 24 | "author": "Evan You", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/vuejs/core/issues" 28 | }, 29 | "homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-ssr#readme", 30 | "dependencies": { 31 | "@vue/shared": "workspace:*", 32 | "@vue/compiler-dom": "workspace:*" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/compiler-ssr/src/errors.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type CompilerError, 3 | DOMErrorCodes, 4 | type SourceLocation, 5 | createCompilerError, 6 | } from '@vue/compiler-dom' 7 | 8 | export interface SSRCompilerError extends CompilerError { 9 | code: SSRErrorCodes 10 | } 11 | 12 | export function createSSRCompilerError( 13 | code: SSRErrorCodes, 14 | loc?: SourceLocation, 15 | ) { 16 | return createCompilerError(code, loc, SSRErrorMessages) as SSRCompilerError 17 | } 18 | 19 | export enum SSRErrorCodes { 20 | X_SSR_UNSAFE_ATTR_NAME = 65 /* DOMErrorCodes.__EXTEND_POINT__ */, 21 | X_SSR_NO_TELEPORT_TARGET, 22 | X_SSR_INVALID_AST_NODE, 23 | } 24 | 25 | if (__TEST__) { 26 | // esbuild cannot infer enum increments if first value is from another 27 | // file, so we have to manually keep them in sync. this check ensures it 28 | // errors out if there are collisions. 29 | if (SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME < DOMErrorCodes.__EXTEND_POINT__) { 30 | throw new Error( 31 | `SSRErrorCodes need to be updated to ${ 32 | DOMErrorCodes.__EXTEND_POINT__ + 1 33 | } to match extension point from core DOMErrorCodes.`, 34 | ) 35 | } 36 | } 37 | 38 | export const SSRErrorMessages: { [code: number]: string } = { 39 | [SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME]: `Unsafe attribute name for SSR.`, 40 | [SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET]: `Missing the 'to' prop on teleport element.`, 41 | [SSRErrorCodes.X_SSR_INVALID_AST_NODE]: `Invalid AST node during SSR transform.`, 42 | } 43 | -------------------------------------------------------------------------------- /packages/compiler-ssr/src/transforms/ssrTransformTransition.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type ComponentNode, 3 | NodeTypes, 4 | type TransformContext, 5 | findProp, 6 | } from '@vue/compiler-dom' 7 | import { 8 | type SSRTransformContext, 9 | processChildren, 10 | } from '../ssrCodegenTransform' 11 | 12 | const wipMap = new WeakMap() 13 | 14 | export function ssrTransformTransition( 15 | node: ComponentNode, 16 | context: TransformContext, 17 | ) { 18 | return (): void => { 19 | const appear = findProp(node, 'appear', false, true) 20 | wipMap.set(node, !!appear) 21 | } 22 | } 23 | 24 | export function ssrProcessTransition( 25 | node: ComponentNode, 26 | context: SSRTransformContext, 27 | ): void { 28 | // #5351: filter out comment children inside transition 29 | node.children = node.children.filter(c => c.type !== NodeTypes.COMMENT) 30 | 31 | const appear = wipMap.get(node) 32 | if (appear) { 33 | context.pushStringPart(``) 36 | } else { 37 | processChildren(node, context, false, true) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/compiler-ssr/src/transforms/ssrVFor.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type ForNode, 3 | type NodeTransform, 4 | NodeTypes, 5 | createCallExpression, 6 | createForLoopParams, 7 | createFunctionExpression, 8 | createStructuralDirectiveTransform, 9 | processFor, 10 | } from '@vue/compiler-dom' 11 | import { 12 | type SSRTransformContext, 13 | processChildrenAsStatement, 14 | } from '../ssrCodegenTransform' 15 | import { SSR_RENDER_LIST } from '../runtimeHelpers' 16 | 17 | // Plugin for the first transform pass, which simply constructs the AST node 18 | export const ssrTransformFor: NodeTransform = 19 | createStructuralDirectiveTransform('for', processFor) 20 | 21 | // This is called during the 2nd transform pass to construct the SSR-specific 22 | // codegen nodes. 23 | export function ssrProcessFor( 24 | node: ForNode, 25 | context: SSRTransformContext, 26 | disableNestedFragments = false, 27 | ): void { 28 | const needFragmentWrapper = 29 | !disableNestedFragments && 30 | (node.children.length !== 1 || node.children[0].type !== NodeTypes.ELEMENT) 31 | const renderLoop = createFunctionExpression( 32 | createForLoopParams(node.parseResult), 33 | ) 34 | renderLoop.body = processChildrenAsStatement( 35 | node, 36 | context, 37 | needFragmentWrapper, 38 | ) 39 | // v-for always renders a fragment unless explicitly disabled 40 | if (!disableNestedFragments) { 41 | context.pushStringPart(``) 42 | } 43 | context.pushStatement( 44 | createCallExpression(context.helper(SSR_RENDER_LIST), [ 45 | node.source, 46 | renderLoop, 47 | ]), 48 | ) 49 | if (!disableNestedFragments) { 50 | context.pushStringPart(``) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/compiler-ssr/src/transforms/ssrVShow.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DOMErrorCodes, 3 | type DirectiveTransform, 4 | createConditionalExpression, 5 | createDOMCompilerError, 6 | createObjectExpression, 7 | createObjectProperty, 8 | createSimpleExpression, 9 | } from '@vue/compiler-dom' 10 | 11 | export const ssrTransformShow: DirectiveTransform = (dir, node, context) => { 12 | if (!dir.exp) { 13 | context.onError( 14 | createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION), 15 | ) 16 | } 17 | return { 18 | props: [ 19 | createObjectProperty( 20 | `style`, 21 | createConditionalExpression( 22 | dir.exp!, 23 | createSimpleExpression(`null`, false), 24 | createObjectExpression([ 25 | createObjectProperty( 26 | `display`, 27 | createSimpleExpression(`none`, true), 28 | ), 29 | ]), 30 | false /* no newline */, 31 | ), 32 | ), 33 | ], 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/global.d.ts: -------------------------------------------------------------------------------- 1 | // Global compile-time constants 2 | declare var __DEV__: boolean 3 | declare var __TEST__: boolean 4 | declare var __BROWSER__: boolean 5 | declare var __GLOBAL__: boolean 6 | declare var __ESM_BUNDLER__: boolean 7 | declare var __ESM_BROWSER__: boolean 8 | declare var __CJS__: boolean 9 | declare var __SSR__: boolean 10 | declare var __VERSION__: string 11 | declare var __COMPAT__: boolean 12 | 13 | // Feature flags 14 | declare var __FEATURE_OPTIONS_API__: boolean 15 | declare var __FEATURE_PROD_DEVTOOLS__: boolean 16 | declare var __FEATURE_SUSPENSE__: boolean 17 | declare var __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: boolean 18 | 19 | declare module '*.vue' {} 20 | 21 | declare module 'estree-walker' { 22 | export function walk( 23 | root: T, 24 | options: { 25 | enter?: (node: T, parent: T | null) => any 26 | leave?: (node: T, parent: T | null) => any 27 | exit?: (node: T) => any 28 | } & ThisType<{ skip: () => void }>, 29 | ) 30 | } 31 | 32 | declare interface String { 33 | /** 34 | * @deprecated Please use String.prototype.slice instead of String.prototype.substring in the repository. 35 | */ 36 | substring(start: number, end?: number): string 37 | } 38 | -------------------------------------------------------------------------------- /packages/reactivity/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/reactivity/README.md: -------------------------------------------------------------------------------- 1 | # @vue/reactivity 2 | 3 | ## Usage Note 4 | 5 | This package is inlined into Global & Browser ESM builds of user-facing renderers (e.g. `@vue/runtime-dom`), but also published as a package that can be used standalone. The standalone build should not be used alongside a pre-bundled build of a user-facing renderer, as they will have different internal storage for reactivity connections. A user-facing renderer should re-export all APIs from this package. 6 | 7 | For full exposed APIs, see `src/index.ts`. 8 | 9 | ## Credits 10 | 11 | The implementation of this module is inspired by the following prior art in the JavaScript ecosystem: 12 | 13 | - [Meteor Tracker](https://docs.meteor.com/api/tracker.html) 14 | - [nx-js/observer-util](https://github.com/nx-js/observer-util) 15 | - [salesforce/observable-membrane](https://github.com/salesforce/observable-membrane) 16 | 17 | ## Caveats 18 | 19 | - Built-in objects are not observed except for `Array`, `Map`, `WeakMap`, `Set` and `WeakSet`. 20 | -------------------------------------------------------------------------------- /packages/reactivity/__benchmarks__/reactiveObject.bench.ts: -------------------------------------------------------------------------------- 1 | import { bench } from 'vitest' 2 | import { reactive } from '../dist/reactivity.esm-browser.prod' 3 | 4 | bench('create reactive obj', () => { 5 | reactive({ a: 1 }) 6 | }) 7 | 8 | { 9 | const r = reactive({ a: 1 }) 10 | bench('read reactive obj property', () => { 11 | r.a 12 | }) 13 | } 14 | 15 | { 16 | let i = 0 17 | const r = reactive({ a: 1 }) 18 | bench('write reactive obj property', () => { 19 | r.a = i++ 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /packages/reactivity/__benchmarks__/ref.bench.ts: -------------------------------------------------------------------------------- 1 | import { bench, describe } from 'vitest' 2 | import { ref } from '../dist/reactivity.esm-browser.prod' 3 | 4 | describe('ref', () => { 5 | bench('create ref', () => { 6 | ref(100) 7 | }) 8 | 9 | { 10 | let i = 0 11 | const v = ref(100) 12 | bench('write ref', () => { 13 | v.value = i++ 14 | }) 15 | } 16 | 17 | { 18 | const v = ref(100) 19 | bench('read ref', () => { 20 | v.value 21 | }) 22 | } 23 | 24 | { 25 | let i = 0 26 | const v = ref(100) 27 | bench('write/read ref', () => { 28 | v.value = i++ 29 | v.value 30 | }) 31 | } 32 | }) 33 | -------------------------------------------------------------------------------- /packages/reactivity/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | if (process.env.NODE_ENV === 'production') { 4 | module.exports = require('./dist/reactivity.cjs.prod.js') 5 | } else { 6 | module.exports = require('./dist/reactivity.cjs.js') 7 | } 8 | -------------------------------------------------------------------------------- /packages/reactivity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/reactivity", 3 | "version": "3.5.16", 4 | "description": "@vue/reactivity", 5 | "main": "index.js", 6 | "module": "dist/reactivity.esm-bundler.js", 7 | "types": "dist/reactivity.d.ts", 8 | "unpkg": "dist/reactivity.global.js", 9 | "jsdelivr": "dist/reactivity.global.js", 10 | "files": [ 11 | "index.js", 12 | "dist" 13 | ], 14 | "exports": { 15 | ".": { 16 | "types": "./dist/reactivity.d.ts", 17 | "node": { 18 | "production": "./dist/reactivity.cjs.prod.js", 19 | "development": "./dist/reactivity.cjs.js", 20 | "default": "./index.js" 21 | }, 22 | "module": "./dist/reactivity.esm-bundler.js", 23 | "import": "./dist/reactivity.esm-bundler.js", 24 | "require": "./index.js" 25 | }, 26 | "./*": "./*" 27 | }, 28 | "sideEffects": false, 29 | "repository": { 30 | "type": "git", 31 | "url": "git+https://github.com/vuejs/core.git", 32 | "directory": "packages/reactivity" 33 | }, 34 | "buildOptions": { 35 | "name": "VueReactivity", 36 | "formats": [ 37 | "esm-bundler", 38 | "esm-browser", 39 | "cjs", 40 | "global" 41 | ] 42 | }, 43 | "keywords": [ 44 | "vue" 45 | ], 46 | "author": "Evan You", 47 | "license": "MIT", 48 | "bugs": { 49 | "url": "https://github.com/vuejs/core/issues" 50 | }, 51 | "homepage": "https://github.com/vuejs/core/tree/main/packages/reactivity#readme", 52 | "dependencies": { 53 | "@vue/shared": "workspace:*" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/reactivity/src/constants.ts: -------------------------------------------------------------------------------- 1 | // using literal strings instead of numbers so that it's easier to inspect 2 | // debugger events 3 | 4 | export enum TrackOpTypes { 5 | GET = 'get', 6 | HAS = 'has', 7 | ITERATE = 'iterate', 8 | } 9 | 10 | export enum TriggerOpTypes { 11 | SET = 'set', 12 | ADD = 'add', 13 | DELETE = 'delete', 14 | CLEAR = 'clear', 15 | } 16 | 17 | export enum ReactiveFlags { 18 | SKIP = '__v_skip', 19 | IS_REACTIVE = '__v_isReactive', 20 | IS_READONLY = '__v_isReadonly', 21 | IS_SHALLOW = '__v_isShallow', 22 | RAW = '__v_raw', 23 | IS_REF = '__v_isRef', 24 | } 25 | -------------------------------------------------------------------------------- /packages/reactivity/src/warning.ts: -------------------------------------------------------------------------------- 1 | export function warn(msg: string, ...args: any[]): void { 2 | console.warn(`[Vue warn] ${msg}`, ...args) 3 | } 4 | -------------------------------------------------------------------------------- /packages/runtime-core/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/runtime-core/README.md: -------------------------------------------------------------------------------- 1 | # @vue/runtime-core 2 | 3 | > This package is published only for typing and building custom renderers. It is NOT meant to be used in applications. 4 | 5 | For full exposed APIs, see `src/index.ts`. 6 | 7 | ## Building a Custom Renderer 8 | 9 | ```ts 10 | import { createRenderer } from '@vue/runtime-core' 11 | 12 | const { render, createApp } = createRenderer({ 13 | patchProp, 14 | insert, 15 | remove, 16 | createElement, 17 | // ... 18 | }) 19 | 20 | // `render` is the low-level API 21 | // `createApp` returns an app instance with configurable context shared 22 | // by the entire app tree. 23 | export { render, createApp } 24 | 25 | export * from '@vue/runtime-core' 26 | ``` 27 | 28 | See `@vue/runtime-dom` for how a DOM-targeting renderer is implemented. 29 | -------------------------------------------------------------------------------- /packages/runtime-core/__tests__/apiWatch.bench.ts: -------------------------------------------------------------------------------- 1 | import { nextTick, ref, watch, watchEffect } from '../src' 2 | import { bench } from 'vitest' 3 | 4 | bench('create watcher', () => { 5 | const v = ref(100) 6 | watch(v, v => {}) 7 | }) 8 | 9 | { 10 | const v = ref(100) 11 | watch(v, v => {}) 12 | let i = 0 13 | bench('update ref to trigger watcher (scheduled but not executed)', () => { 14 | v.value = i++ 15 | }) 16 | } 17 | 18 | { 19 | const v = ref(100) 20 | watch(v, v => {}) 21 | let i = 0 22 | bench('update ref to trigger watcher (executed)', async () => { 23 | v.value = i++ 24 | return nextTick() 25 | }) 26 | } 27 | 28 | { 29 | bench('create watchEffect', () => { 30 | watchEffect(() => {}) 31 | }) 32 | } 33 | 34 | { 35 | const v = ref(100) 36 | watchEffect(() => { 37 | v.value 38 | }) 39 | let i = 0 40 | bench( 41 | 'update ref to trigger watchEffect (scheduled but not executed)', 42 | () => { 43 | v.value = i++ 44 | }, 45 | ) 46 | } 47 | 48 | { 49 | const v = ref(100) 50 | watchEffect(() => { 51 | v.value 52 | }) 53 | let i = 0 54 | bench('update ref to trigger watchEffect (executed)', async () => { 55 | v.value = i++ 56 | await nextTick() 57 | }) 58 | } 59 | -------------------------------------------------------------------------------- /packages/runtime-core/__tests__/helpers/toHandlers.spec.ts: -------------------------------------------------------------------------------- 1 | import { toHandlers } from '../../src/helpers/toHandlers' 2 | 3 | describe('toHandlers', () => { 4 | it('should not accept non-objects', () => { 5 | toHandlers(null as any) 6 | toHandlers(undefined as any) 7 | 8 | expect( 9 | 'v-on with no argument expects an object value.', 10 | ).toHaveBeenWarnedTimes(2) 11 | }) 12 | 13 | it('should properly change object keys', () => { 14 | const input = () => {} 15 | const change = () => {} 16 | 17 | expect(toHandlers({ input, change })).toStrictEqual({ 18 | onInput: input, 19 | onChange: change, 20 | }) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/runtime-core/__tests__/misc.spec.ts: -------------------------------------------------------------------------------- 1 | import { h, isReactive, nodeOps, reactive, render } from '@vue/runtime-test' 2 | 3 | describe('misc', () => { 4 | test('component public instance should not be observable', () => { 5 | let instance: any 6 | const Comp = { 7 | render() {}, 8 | mounted() { 9 | instance = this 10 | }, 11 | } 12 | render(h(Comp), nodeOps.createElement('div')) 13 | expect(instance).toBeDefined() 14 | const r = reactive(instance) 15 | expect(r).toBe(instance) 16 | expect(isReactive(r)).toBe(false) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /packages/runtime-core/__tests__/rendererElement.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type TestElement, 3 | h, 4 | serializeInner as inner, 5 | nodeOps, 6 | render, 7 | } from '@vue/runtime-test' 8 | 9 | describe('renderer: element', () => { 10 | let root: TestElement 11 | 12 | beforeEach(() => { 13 | root = nodeOps.createElement('div') 14 | }) 15 | 16 | it('should create an element', () => { 17 | render(h('div'), root) 18 | expect(inner(root)).toBe('
') 19 | }) 20 | 21 | it('should create an element with props', () => { 22 | render(h('div', { id: 'foo', class: 'bar' }), root) 23 | expect(inner(root)).toBe('
') 24 | }) 25 | 26 | it('should create an element with direct text children', () => { 27 | render(h('div', ['foo', ' ', 'bar']), root) 28 | expect(inner(root)).toBe('
foo bar
') 29 | }) 30 | 31 | it('should create an element with direct text children and props', () => { 32 | render(h('div', { id: 'foo' }, ['bar']), root) 33 | expect(inner(root)).toBe('
bar
') 34 | }) 35 | 36 | it('should update an element tag which is already mounted', () => { 37 | render(h('div', ['foo']), root) 38 | expect(inner(root)).toBe('
foo
') 39 | 40 | render(h('span', ['foo']), root) 41 | expect(inner(root)).toBe('foo') 42 | }) 43 | 44 | it('should update element props which is already mounted', () => { 45 | render(h('div', { id: 'bar' }, ['foo']), root) 46 | expect(inner(root)).toBe('
foo
') 47 | 48 | render(h('div', { id: 'baz', class: 'bar' }, ['foo']), root) 49 | expect(inner(root)).toBe('
foo
') 50 | }) 51 | }) 52 | -------------------------------------------------------------------------------- /packages/runtime-core/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | if (process.env.NODE_ENV === 'production') { 4 | module.exports = require('./dist/runtime-core.cjs.prod.js') 5 | } else { 6 | module.exports = require('./dist/runtime-core.cjs.js') 7 | } 8 | -------------------------------------------------------------------------------- /packages/runtime-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vue/runtime-core", 3 | "version": "3.5.16", 4 | "description": "@vue/runtime-core", 5 | "main": "index.js", 6 | "module": "dist/runtime-core.esm-bundler.js", 7 | "types": "dist/runtime-core.d.ts", 8 | "files": [ 9 | "index.js", 10 | "dist" 11 | ], 12 | "exports": { 13 | ".": { 14 | "types": "./dist/runtime-core.d.ts", 15 | "node": { 16 | "production": "./dist/runtime-core.cjs.prod.js", 17 | "development": "./dist/runtime-core.cjs.js", 18 | "default": "./index.js" 19 | }, 20 | "module": "./dist/runtime-core.esm-bundler.js", 21 | "import": "./dist/runtime-core.esm-bundler.js", 22 | "require": "./index.js" 23 | }, 24 | "./*": "./*" 25 | }, 26 | "buildOptions": { 27 | "name": "VueRuntimeCore", 28 | "formats": [ 29 | "esm-bundler", 30 | "cjs" 31 | ] 32 | }, 33 | "sideEffects": false, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/vuejs/core.git", 37 | "directory": "packages/runtime-core" 38 | }, 39 | "keywords": [ 40 | "vue" 41 | ], 42 | "author": "Evan You", 43 | "license": "MIT", 44 | "bugs": { 45 | "url": "https://github.com/vuejs/core/issues" 46 | }, 47 | "homepage": "https://github.com/vuejs/core/tree/main/packages/runtime-core#readme", 48 | "dependencies": { 49 | "@vue/shared": "workspace:*", 50 | "@vue/reactivity": "workspace:*" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/runtime-core/src/apiComputed.ts: -------------------------------------------------------------------------------- 1 | import { type ComputedRefImpl, computed as _computed } from '@vue/reactivity' 2 | import { getCurrentInstance, isInSSRComponentSetup } from './component' 3 | 4 | export const computed: typeof _computed = ( 5 | getterOrOptions: any, 6 | debugOptions?: any, 7 | ) => { 8 | // @ts-expect-error 9 | const c = _computed(getterOrOptions, debugOptions, isInSSRComponentSetup) 10 | if (__DEV__) { 11 | const i = getCurrentInstance() 12 | if (i && i.appContext.config.warnRecursiveComputed) { 13 | ;(c as unknown as ComputedRefImpl)._warnRecursive = true 14 | } 15 | } 16 | return c as any 17 | } 18 | -------------------------------------------------------------------------------- /packages/runtime-core/src/compat/attrsFallthrough.ts: -------------------------------------------------------------------------------- 1 | import { isOn } from '@vue/shared' 2 | import type { ComponentInternalInstance } from '../component' 3 | import { DeprecationTypes, isCompatEnabled } from './compatConfig' 4 | 5 | export function shouldSkipAttr( 6 | key: string, 7 | instance: ComponentInternalInstance, 8 | ): boolean { 9 | if (key === 'is') { 10 | return true 11 | } 12 | if ( 13 | (key === 'class' || key === 'style') && 14 | isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance) 15 | ) { 16 | return true 17 | } 18 | if ( 19 | isOn(key) && 20 | isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance) 21 | ) { 22 | return true 23 | } 24 | // vue-router 25 | if (key.startsWith('routerView') || key === 'registerRouteInstance') { 26 | return true 27 | } 28 | return false 29 | } 30 | -------------------------------------------------------------------------------- /packages/runtime-core/src/compat/component.ts: -------------------------------------------------------------------------------- 1 | import { isFunction, isObject } from '@vue/shared' 2 | import type { Component, ComponentInternalInstance } from '../component' 3 | import { 4 | DeprecationTypes, 5 | checkCompatEnabled, 6 | softAssertCompatEnabled, 7 | } from './compatConfig' 8 | import { convertLegacyAsyncComponent } from './componentAsync' 9 | import { convertLegacyFunctionalComponent } from './componentFunctional' 10 | 11 | export function convertLegacyComponent( 12 | comp: any, 13 | instance: ComponentInternalInstance | null, 14 | ): Component { 15 | if (comp.__isBuiltIn) { 16 | return comp 17 | } 18 | 19 | // 2.x constructor 20 | if (isFunction(comp) && comp.cid) { 21 | // #7766 22 | if (comp.render) { 23 | // only necessary when compiled from SFC 24 | comp.options.render = comp.render 25 | } 26 | // copy over internal properties set by the SFC compiler 27 | comp.options.__file = comp.__file 28 | comp.options.__hmrId = comp.__hmrId 29 | comp.options.__scopeId = comp.__scopeId 30 | comp = comp.options 31 | } 32 | 33 | // 2.x async component 34 | if ( 35 | isFunction(comp) && 36 | checkCompatEnabled(DeprecationTypes.COMPONENT_ASYNC, instance, comp) 37 | ) { 38 | // since after disabling this, plain functions are still valid usage, do not 39 | // use softAssert here. 40 | return convertLegacyAsyncComponent(comp) 41 | } 42 | 43 | // 2.x functional component 44 | if ( 45 | isObject(comp) && 46 | comp.functional && 47 | softAssertCompatEnabled( 48 | DeprecationTypes.COMPONENT_FUNCTIONAL, 49 | instance, 50 | comp, 51 | ) 52 | ) { 53 | return convertLegacyFunctionalComponent(comp) 54 | } 55 | 56 | return comp 57 | } 58 | -------------------------------------------------------------------------------- /packages/runtime-core/src/compat/data.ts: -------------------------------------------------------------------------------- 1 | import { isPlainObject } from '@vue/shared' 2 | import { DeprecationTypes, warnDeprecation } from './compatConfig' 3 | 4 | export function deepMergeData(to: any, from: any): any { 5 | for (const key in from) { 6 | const toVal = to[key] 7 | const fromVal = from[key] 8 | if (key in to && isPlainObject(toVal) && isPlainObject(fromVal)) { 9 | __DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DATA_MERGE, null, key) 10 | deepMergeData(toVal, fromVal) 11 | } else { 12 | to[key] = fromVal 13 | } 14 | } 15 | return to 16 | } 17 | -------------------------------------------------------------------------------- /packages/runtime-core/src/compat/instanceChildren.ts: -------------------------------------------------------------------------------- 1 | import { ShapeFlags } from '@vue/shared' 2 | import type { ComponentInternalInstance } from '../component' 3 | import type { ComponentPublicInstance } from '../componentPublicInstance' 4 | import type { VNode } from '../vnode' 5 | import { DeprecationTypes, assertCompatEnabled } from './compatConfig' 6 | 7 | export function getCompatChildren( 8 | instance: ComponentInternalInstance, 9 | ): ComponentPublicInstance[] { 10 | assertCompatEnabled(DeprecationTypes.INSTANCE_CHILDREN, instance) 11 | const root = instance.subTree 12 | const children: ComponentPublicInstance[] = [] 13 | if (root) { 14 | walk(root, children) 15 | } 16 | return children 17 | } 18 | 19 | function walk(vnode: VNode, children: ComponentPublicInstance[]) { 20 | if (vnode.component) { 21 | children.push(vnode.component.proxy!) 22 | } else if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { 23 | const vnodes = vnode.children as VNode[] 24 | for (let i = 0; i < vnodes.length; i++) { 25 | walk(vnodes[i], children) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/runtime-core/src/compat/instanceListeners.ts: -------------------------------------------------------------------------------- 1 | import { isOn } from '@vue/shared' 2 | import type { ComponentInternalInstance } from '../component' 3 | import { DeprecationTypes, assertCompatEnabled } from './compatConfig' 4 | 5 | export function getCompatListeners( 6 | instance: ComponentInternalInstance, 7 | ): Record { 8 | assertCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance) 9 | 10 | const listeners: Record = {} 11 | const rawProps = instance.vnode.props 12 | if (!rawProps) { 13 | return listeners 14 | } 15 | for (const key in rawProps) { 16 | if (isOn(key)) { 17 | listeners[key[2].toLowerCase() + key.slice(3)] = rawProps[key] 18 | } 19 | } 20 | return listeners 21 | } 22 | -------------------------------------------------------------------------------- /packages/runtime-core/src/compat/props.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from '@vue/shared' 2 | import { inject } from '../apiInject' 3 | import type { ComponentInternalInstance, Data } from '../component' 4 | import { 5 | type ComponentOptions, 6 | resolveMergedOptions, 7 | } from '../componentOptions' 8 | import { DeprecationTypes, warnDeprecation } from './compatConfig' 9 | 10 | export function createPropsDefaultThis( 11 | instance: ComponentInternalInstance, 12 | rawProps: Data, 13 | propKey: string, 14 | ): object { 15 | return new Proxy( 16 | {}, 17 | { 18 | get(_, key: string) { 19 | __DEV__ && 20 | warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey) 21 | // $options 22 | if (key === '$options') { 23 | return resolveMergedOptions(instance) 24 | } 25 | // props 26 | if (key in rawProps) { 27 | return rawProps[key] 28 | } 29 | // injections 30 | const injections = (instance.type as ComponentOptions).inject 31 | if (injections) { 32 | if (isArray(injections)) { 33 | if (injections.includes(key)) { 34 | return inject(key) 35 | } 36 | } else if (key in injections) { 37 | return inject(key) 38 | } 39 | } 40 | }, 41 | }, 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /packages/runtime-core/src/enums.ts: -------------------------------------------------------------------------------- 1 | export enum LifecycleHooks { 2 | BEFORE_CREATE = 'bc', 3 | CREATED = 'c', 4 | BEFORE_MOUNT = 'bm', 5 | MOUNTED = 'm', 6 | BEFORE_UPDATE = 'bu', 7 | UPDATED = 'u', 8 | BEFORE_UNMOUNT = 'bum', 9 | UNMOUNTED = 'um', 10 | DEACTIVATED = 'da', 11 | ACTIVATED = 'a', 12 | RENDER_TRIGGERED = 'rtg', 13 | RENDER_TRACKED = 'rtc', 14 | ERROR_CAPTURED = 'ec', 15 | SERVER_PREFETCH = 'sp', 16 | } 17 | -------------------------------------------------------------------------------- /packages/runtime-core/src/featureFlags.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalThis } from '@vue/shared' 2 | 3 | /** 4 | * This is only called in esm-bundler builds. 5 | * It is called when a renderer is created, in `baseCreateRenderer` so that 6 | * importing runtime-core is side-effects free. 7 | */ 8 | export function initFeatureFlags(): void { 9 | const needWarn = [] 10 | 11 | if (typeof __FEATURE_OPTIONS_API__ !== 'boolean') { 12 | __DEV__ && needWarn.push(`__VUE_OPTIONS_API__`) 13 | getGlobalThis().__VUE_OPTIONS_API__ = true 14 | } 15 | 16 | if (typeof __FEATURE_PROD_DEVTOOLS__ !== 'boolean') { 17 | __DEV__ && needWarn.push(`__VUE_PROD_DEVTOOLS__`) 18 | getGlobalThis().__VUE_PROD_DEVTOOLS__ = false 19 | } 20 | 21 | if (typeof __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__ !== 'boolean') { 22 | __DEV__ && needWarn.push(`__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`) 23 | getGlobalThis().__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false 24 | } 25 | 26 | if (__DEV__ && needWarn.length) { 27 | const multi = needWarn.length > 1 28 | console.warn( 29 | `Feature flag${multi ? `s` : ``} ${needWarn.join(', ')} ${ 30 | multi ? `are` : `is` 31 | } not explicitly defined. You are running the esm-bundler build of Vue, ` + 32 | `which expects these compile-time feature flags to be globally injected ` + 33 | `via the bundler config in order to get better tree-shaking in the ` + 34 | `production bundle.\n\n` + 35 | `For more details, see https://link.vuejs.org/feature-flags.`, 36 | ) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/runtime-core/src/helpers/createSlots.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from '@vue/shared' 2 | import type { VNode } from '../vnode' 3 | 4 | // #6651 res can be undefined in SSR in string push mode 5 | type SSRSlot = (...args: any[]) => VNode[] | undefined 6 | 7 | interface CompiledSlotDescriptor { 8 | name: string 9 | fn: SSRSlot 10 | key?: string 11 | } 12 | 13 | /** 14 | * Compiler runtime helper for creating dynamic slots object 15 | * @private 16 | */ 17 | export function createSlots( 18 | slots: Record, 19 | dynamicSlots: ( 20 | | CompiledSlotDescriptor 21 | | CompiledSlotDescriptor[] 22 | | undefined 23 | )[], 24 | ): Record { 25 | for (let i = 0; i < dynamicSlots.length; i++) { 26 | const slot = dynamicSlots[i] 27 | // array of dynamic slot generated by