wip: make sfc playground work after refactor + support dev mode

This commit is contained in:
Evan You 2024-12-04 15:07:40 +08:00
parent 3a6915b587
commit b1b3baeb6e
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
7 changed files with 59 additions and 35 deletions

View File

@ -4,21 +4,21 @@
"packageManager": "pnpm@9.12.3", "packageManager": "pnpm@9.12.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "node scripts/dev.js vue vue-vapor", "dev": "node scripts/dev.js vue runtime-vapor",
"build": "node scripts/build.js", "build": "node scripts/build.js",
"build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js", "build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js",
"clean": "rimraf --glob packages/*/dist temp .eslintcache", "clean": "rimraf --glob packages/*/dist temp .eslintcache",
"size": "run-s \"size-*\" && node scripts/usage-size.js", "size": "run-s \"size-*\" && node scripts/usage-size.js",
"size-global": "node scripts/build.js vue vue-vapor runtime-dom runtime-vapor compiler-dom -f global -p --size", "size-global": "node scripts/build.js vue runtime-vapor runtime-dom runtime-vapor compiler-dom -f global -p --size",
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime", "size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
"size-esm": "node scripts/build.js runtime-shared runtime-dom runtime-vapor runtime-core reactivity shared vue-vapor -f esm-bundler", "size-esm": "node scripts/build.js runtime-shared runtime-dom runtime-vapor runtime-core reactivity shared runtime-vapor -f esm-bundler",
"check": "tsc --incremental --noEmit", "check": "tsc --incremental --noEmit",
"lint": "eslint --cache .", "lint": "eslint --cache .",
"format": "prettier --write --cache .", "format": "prettier --write --cache .",
"format-check": "prettier --check --cache .", "format-check": "prettier --check --cache .",
"test": "vitest", "test": "vitest",
"test-unit": "vitest --project unit", "test-unit": "vitest --project unit",
"test-e2e": "node scripts/build.js vue vue-vapor -f global -d && vitest --project e2e", "test-e2e": "node scripts/build.js vue runtime-vapor -f global -d && vitest --project e2e",
"test-dts": "run-s build-dts test-dts-only", "test-dts": "run-s build-dts test-dts-only",
"test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json", "test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json",
"test-coverage": "vitest run --project unit --coverage", "test-coverage": "vitest run --project unit --coverage",
@ -41,7 +41,7 @@
"build-all-cjs": "node scripts/build.js vue runtime compiler reactivity shared -af cjs", "build-all-cjs": "node scripts/build.js vue runtime compiler reactivity shared -af cjs",
"build-runtime-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js vue -f esm-browser-runtime", "build-runtime-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js vue -f esm-browser-runtime",
"build-browser-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler && node scripts/build.js vue -f esm-browser", "build-browser-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler && node scripts/build.js vue -f esm-browser",
"build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer vue-vapor -f esm-browser", "build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer runtime-vapor -f esm-browser",
"build-sfc-playground-self": "cd packages-private/sfc-playground && npm run build", "build-sfc-playground-self": "cd packages-private/sfc-playground && npm run build",
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"postinstall": "simple-git-hooks" "postinstall": "simple-git-hooks"

View File

@ -57,7 +57,6 @@ const importMap = computed(() => {
'vue/vapor': vapor, 'vue/vapor': vapor,
}, },
} }
if (useVaporMode.value) vaporImportMap.imports!.vue = vapor
return mergeImportMap(vueImportMap.value, vaporImportMap) return mergeImportMap(vueImportMap.value, vaporImportMap)
}) })

View File

@ -0,0 +1,7 @@
import type { VaporComponent } from './component'
/*! #__NO_SIDE_EFFECTS__ */
export function defineComponent(comp: VaporComponent): VaporComponent {
// TODO type inference
return comp
}

View File

@ -10,6 +10,19 @@ export type Fragment = {
[fragmentKey]: true [fragmentKey]: true
} }
export function isFragment(val: NonNullable<unknown>): val is Fragment {
return fragmentKey in val
}
export function isBlock(val: NonNullable<unknown>): val is Block {
return (
val instanceof Node ||
isArray(val) ||
isVaporComponent(val) ||
isFragment(val)
)
}
/*! #__NO_SIDE_EFFECTS__ */ /*! #__NO_SIDE_EFFECTS__ */
export function normalizeBlock(block: Block): Node[] { export function normalizeBlock(block: Block): Node[] {
const nodes: Node[] = [] const nodes: Node[] = []

View File

@ -2,6 +2,7 @@ import {
type ComponentInternalOptions, type ComponentInternalOptions,
type ComponentPropsOptions, type ComponentPropsOptions,
EffectScope, EffectScope,
type EmitFn,
type EmitsOptions, type EmitsOptions,
type GenericAppContext, type GenericAppContext,
type GenericComponentInstance, type GenericComponentInstance,
@ -11,8 +12,9 @@ import {
nextUid, nextUid,
popWarningContext, popWarningContext,
pushWarningContext, pushWarningContext,
warn,
} from '@vue/runtime-dom' } from '@vue/runtime-dom'
import type { Block } from './block' import { type Block, isBlock } from './block'
import { pauseTracking, resetTracking } from '@vue/reactivity' import { pauseTracking, resetTracking } from '@vue/reactivity'
import { EMPTY_OBJ, isFunction } from '@vue/shared' import { EMPTY_OBJ, isFunction } from '@vue/shared'
import { import {
@ -22,6 +24,7 @@ import {
} from './componentProps' } from './componentProps'
import { setDynamicProp } from './dom/prop' import { setDynamicProp } from './dom/prop'
import { renderEffect } from './renderEffect' import { renderEffect } from './renderEffect'
import { emit } from './componentEmits'
export type VaporComponent = FunctionalVaporComponent | ObjectVaporComponent export type VaporComponent = FunctionalVaporComponent | ObjectVaporComponent
@ -93,11 +96,29 @@ export function createComponent(
const setupFn = isFunction(component) ? component : component.setup const setupFn = isFunction(component) ? component : component.setup
const setupContext = setupFn!.length > 1 ? new SetupContext(instance) : null const setupContext = setupFn!.length > 1 ? new SetupContext(instance) : null
instance.block = setupFn!( const setupResult =
instance.props, setupFn!(
// @ts-expect-error instance.props,
setupContext, // @ts-expect-error
) as Block // TODO handle return object setupContext,
) || EMPTY_OBJ
if (__DEV__ && !isBlock(setupResult)) {
if (isFunction(component)) {
warn(`Functional vapor component must return a block directly.`)
instance.block = []
} else if (!component.render) {
warn(
`Vapor component setup() returned non-block value, and has no render function.`,
)
instance.block = []
} else {
instance.block = component.render.call(null, setupResult)
}
} else {
// in prod result can only be block
instance.block = setupResult as Block
}
// single root, inherit attrs // single root, inherit attrs
if ( if (
@ -161,6 +182,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
ec: LifecycleHook ec: LifecycleHook
// dev only // dev only
setupState?: Record<string, any>
propsOptions?: NormalizedPropsOptions propsOptions?: NormalizedPropsOptions
emitsOptions?: ObjectEmitsOptions | null emitsOptions?: ObjectEmitsOptions | null
@ -208,13 +230,13 @@ export function isVaporComponent(
export class SetupContext<E = EmitsOptions> { export class SetupContext<E = EmitsOptions> {
attrs: Record<string, any> attrs: Record<string, any>
// emit: EmitFn<E> emit: EmitFn<E>
// slots: Readonly<StaticSlots> // slots: Readonly<StaticSlots>
expose: (exposed?: Record<string, any>) => void expose: (exposed?: Record<string, any>) => void
constructor(instance: VaporComponentInstance) { constructor(instance: VaporComponentInstance) {
this.attrs = instance.attrs this.attrs = instance.attrs
// this.emit = instance.emit as EmitFn<E> this.emit = emit.bind(null, instance) as EmitFn<E>
// this.slots = instance.slots // this.slots = instance.slots
this.expose = (exposed = {}) => { this.expose = (exposed = {}) => {
instance.exposed = exposed instance.exposed = exposed

View File

@ -1,14 +1,6 @@
import { import { type ObjectEmitsOptions, baseEmit } from '@vue/runtime-dom'
type EmitFn, import type { VaporComponent, VaporComponentInstance } from './component'
type ObjectEmitsOptions, import { EMPTY_OBJ, hasOwn, isArray } from '@vue/shared'
baseEmit,
} from '@vue/runtime-dom'
import {
type VaporComponent,
type VaporComponentInstance,
currentInstance,
} from './component'
import { EMPTY_OBJ, NOOP, hasOwn, isArray } from '@vue/shared'
import { resolveSource } from './componentProps' import { resolveSource } from './componentProps'
/** /**
@ -34,15 +26,6 @@ export function normalizeEmitsOptions(
return (comp.__emitsOptions = normalized) return (comp.__emitsOptions = normalized)
} }
export function useEmit(): EmitFn {
if (!currentInstance) {
// TODO warn
return NOOP
} else {
return emit.bind(null, currentInstance)
}
}
export function emit( export function emit(
instance: VaporComponentInstance, instance: VaporComponentInstance,
event: string, event: string,

View File

@ -1,7 +1,7 @@
export { createComponent } from './component' export { createComponent } from './component'
export { renderEffect } from './renderEffect' export { renderEffect } from './renderEffect'
export { createVaporApp } from './apiCreateApp' export { createVaporApp } from './apiCreateApp'
export { useEmit } from './componentEmits' export { defineComponent } from './apiDefineComponent'
// DOM // DOM
export { template, children, next } from './dom/template' export { template, children, next } from './dom/template'