types: generate types for v3 apis

This commit is contained in:
Evan You 2022-05-30 21:36:07 +08:00
parent e5a6fe5da7
commit 2acb5474bc
62 changed files with 957 additions and 104 deletions

9
.gitignore vendored
View File

@ -3,14 +3,7 @@ node_modules
*.log
explorations
TODOs.md
dist/*.gz
dist/*.map
dist/vue.common.min.js
test/e2e/reports
test/e2e/screenshots
coverage
RELEASE_NOTE*.md
dist/*.js
packages/vue-server-renderer/basic.js
packages/vue-server-renderer/build.dev.js
packages/vue-server-renderer/build.prod.js
@ -20,3 +13,5 @@ packages/vue-template-compiler/build.js
packages/vue-template-compiler/browser.js
.vscode
dist
temp
types/v3-generated.d.ts

63
api-extractor.json Normal file
View File

@ -0,0 +1,63 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"projectFolder": ".",
"compiler": {
"tsconfigFilePath": "api-extractor.tsconfig.json"
},
"mainEntryPointFilePath": "./temp/src/v3/index.d.ts",
"dtsRollup": {
"enabled": true,
"publicTrimmedFilePath": "./types/v3-generated.d.ts"
},
"apiReport": {
"enabled": false
},
"docModel": {
"enabled": false
},
"tsdocMetadata": {
"enabled": false
},
"messages": {
"compilerMessageReporting": {
"default": {
"logLevel": "warning"
}
},
"extractorMessageReporting": {
"default": {
"logLevel": "warning",
"addToApiReportFile": true
},
"ae-missing-release-tag": {
"logLevel": "none"
},
"ae-internal-missing-underscore": {
"logLevel": "none"
},
"ae-forgotten-export": {
"logLevel": "none"
}
},
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
},
"tsdoc-undefined-tag": {
"logLevel": "none"
}
}
}
}

View File

@ -0,0 +1,35 @@
{
"compilerOptions": {
"baseUrl": "./temp",
"outDir": "dist",
"sourceMap": true,
"target": "esnext",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"allowJs": true,
"noImplicitAny": false,
"noImplicitThis": false,
"noUnusedLocals": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"removeComments": false,
"jsx": "preserve",
"lib": ["esnext", "dom"],
"paths": {
"compiler/*": ["src/compiler/*"],
"core/*": ["src/core/*"],
"server/*": ["src/server/*"],
"sfc/*": ["src/sfc/*"],
"shared/*": ["src/shared/*"],
"web/*": ["src/platforms/web/*"],
"v3": ["src/v3/index"],
"v3/*": ["src/v3/*"],
"vue": ["src/platforms/web/entry-runtime-with-compiler"]
}
},
"include": ["src", "typescript"]
}

View File

@ -22,12 +22,13 @@
"dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:web-compiler ",
"build": "node scripts/build.js",
"build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
"build:types": "rimraf temp && tsc --declaration --emitDeclarationOnly --outDir temp && api-extractor run",
"test": "npm run lint && npm run ts-check && npm run test:types && npm run test:unit && npm run test:e2e",
"test:unit": "vitest run test/unit",
"test:ssr": "npm run build:ssr && vitest run test/ssr",
"test:e2e": "npm run build -- web-full-prod,web-server-renderer-basic && vitest run test/e2e",
"test:transition": "karma start test/transition/karma.conf.js",
"test:types": "tsc -p ./types/tsconfig.json",
"test:types": "npm run build:types && tsc -p ./types/tsconfig.json",
"format": "prettier --write --parser typescript \"(src|test|packages|types)/**/*.ts\"",
"ts-check": "tsc -p tsconfig.json --noEmit",
"ts-check:test": "tsc -p test/tsconfig.json --noEmit",
@ -62,6 +63,7 @@
},
"homepage": "https://github.com/vuejs/vue#readme",
"devDependencies": {
"@microsoft/api-extractor": "^7.24.2",
"@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-node-resolve": "^13.2.1",
@ -98,6 +100,7 @@
"prettier": "^2.6.2",
"puppeteer": "^14.1.1",
"resolve": "^1.22.0",
"rimraf": "^3.0.2",
"rollup": "^2.70.2",
"rollup-plugin-typescript2": "^0.31.2",
"serialize-javascript": "^6.0.0",

View File

@ -1,6 +1,7 @@
lockfileVersion: 5.4
specifiers:
'@microsoft/api-extractor': ^7.24.2
'@rollup/plugin-alias': ^3.1.9
'@rollup/plugin-commonjs': ^22.0.0
'@rollup/plugin-node-resolve': ^13.2.1
@ -37,6 +38,7 @@ specifiers:
prettier: ^2.6.2
puppeteer: ^14.1.1
resolve: ^1.22.0
rimraf: ^3.0.2
rollup: ^2.70.2
rollup-plugin-typescript2: ^0.31.2
serialize-javascript: ^6.0.0
@ -52,6 +54,7 @@ specifiers:
yorkie: ^2.0.0
devDependencies:
'@microsoft/api-extractor': 7.24.2
'@rollup/plugin-alias': 3.1.9_rollup@2.74.0
'@rollup/plugin-commonjs': 22.0.0_rollup@2.74.0
'@rollup/plugin-node-resolve': 13.3.0_rollup@2.74.0
@ -88,6 +91,7 @@ devDependencies:
prettier: 2.6.2
puppeteer: 14.1.1
resolve: 1.22.0
rimraf: 3.0.2
rollup: 2.74.0
rollup-plugin-typescript2: 0.31.2_dyu3set7imqii5ytavmnwecwpy
serialize-javascript: 6.0.0
@ -205,6 +209,45 @@ packages:
engines: {node: '>=6.9.0'}
dev: true
/@microsoft/api-extractor-model/7.17.3:
resolution: {integrity: sha512-ETslFxVEZTEK6mrOARxM34Ll2W/5H2aTk9Pe9dxsMCnthE8O/CaStV4WZAGsvvZKyjelSWgPVYGowxGVnwOMlQ==}
dependencies:
'@microsoft/tsdoc': 0.14.1
'@microsoft/tsdoc-config': 0.16.1
'@rushstack/node-core-library': 3.45.5
dev: true
/@microsoft/api-extractor/7.24.2:
resolution: {integrity: sha512-QWZh9aQZvBAdRVK+Go8NiW8YNMN//OGiNqgA3iZ2sEy8imUqkRBCybXgmw2HkEYyPnn55CFoMKvnAHvV9+4B/A==}
hasBin: true
dependencies:
'@microsoft/api-extractor-model': 7.17.3
'@microsoft/tsdoc': 0.14.1
'@microsoft/tsdoc-config': 0.16.1
'@rushstack/node-core-library': 3.45.5
'@rushstack/rig-package': 0.3.11
'@rushstack/ts-command-line': 4.11.0
colors: 1.2.5
lodash: 4.17.21
resolve: 1.17.0
semver: 7.3.7
source-map: 0.6.1
typescript: 4.6.4
dev: true
/@microsoft/tsdoc-config/0.16.1:
resolution: {integrity: sha512-2RqkwiD4uN6MLnHFljqBlZIXlt/SaUT6cuogU1w2ARw4nKuuppSmR0+s+NC+7kXBQykd9zzu0P4HtBpZT5zBpQ==}
dependencies:
'@microsoft/tsdoc': 0.14.1
ajv: 6.12.6
jju: 1.4.0
resolve: 1.19.0
dev: true
/@microsoft/tsdoc/0.14.1:
resolution: {integrity: sha512-6Wci+Tp3CgPt/B9B0a3J4s3yMgLNSku6w5TV6mN+61C71UqsRBv2FUibBf3tPGlNxebgPHMEUzKpb1ggE8KCKw==}
dev: true
/@rollup/plugin-alias/3.1.9_rollup@2.74.0:
resolution: {integrity: sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw==}
engines: {node: '>=8.0.0'}
@ -276,6 +319,36 @@ packages:
picomatch: 2.3.1
dev: true
/@rushstack/node-core-library/3.45.5:
resolution: {integrity: sha512-KbN7Hp9vH3bD3YJfv6RnVtzzTAwGYIBl7y2HQLY4WEQqRbvE3LgI78W9l9X+cTAXCX//p0EeoiUYNTFdqJrMZg==}
dependencies:
'@types/node': 12.20.24
colors: 1.2.5
fs-extra: 7.0.1
import-lazy: 4.0.0
jju: 1.4.0
resolve: 1.17.0
semver: 7.3.7
timsort: 0.3.0
z-schema: 5.0.3
dev: true
/@rushstack/rig-package/0.3.11:
resolution: {integrity: sha512-uI1/g5oQPtyrT9nStoyX/xgZSLa2b+srRFaDk3r1eqC7zA5th4/bvTGl2QfV3C9NcP+coSqmk5mFJkUfH6i3Lw==}
dependencies:
resolve: 1.17.0
strip-json-comments: 3.1.1
dev: true
/@rushstack/ts-command-line/4.11.0:
resolution: {integrity: sha512-ptG9L0mjvJ5QtK11GsAFY+jGfsnqHDS6CY6Yw1xT7a9bhjfNYnf6UPwjV+pF6UgiucfNcMDNW9lkDLxvZKKxMg==}
dependencies:
'@types/argparse': 1.0.38
argparse: 1.0.10
colors: 1.2.5
string-argv: 0.3.1
dev: true
/@tootallnate/once/2.0.0:
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
engines: {node: '>= 10'}
@ -297,6 +370,10 @@ packages:
resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==}
dev: true
/@types/argparse/1.0.38:
resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==}
dev: true
/@types/chai-subset/1.3.3:
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
dependencies:
@ -335,6 +412,10 @@ packages:
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
dev: true
/@types/node/12.20.24:
resolution: {integrity: sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==}
dev: true
/@types/node/17.0.34:
resolution: {integrity: sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==}
dev: true
@ -683,6 +764,12 @@ packages:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true
/argparse/1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies:
sprintf-js: 1.0.3
dev: true
/arr-diff/4.0.0:
resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==}
engines: {node: '>=0.10.0'}
@ -1234,6 +1321,11 @@ packages:
resolution: {integrity: sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==}
dev: true
/colors/1.2.5:
resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==}
engines: {node: '>=0.1.90'}
dev: true
/combined-stream/1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
@ -2593,6 +2685,15 @@ packages:
universalify: 2.0.0
dev: true
/fs-extra/7.0.1:
resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
engines: {node: '>=6 <7 || >=8'}
dependencies:
graceful-fs: 4.2.10
jsonfile: 4.0.0
universalify: 0.1.2
dev: true
/fs-extra/8.1.0:
resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
engines: {node: '>=6 <7 || >=8'}
@ -3004,6 +3105,11 @@ packages:
dev: true
optional: true
/import-lazy/4.0.0:
resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
engines: {node: '>=8'}
dev: true
/imurmurhash/0.1.4:
resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=}
engines: {node: '>=0.8.19'}
@ -3019,7 +3125,7 @@ packages:
dev: true
/inflight/1.0.6:
resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
once: 1.4.0
wrappy: 1.0.2
@ -3304,6 +3410,10 @@ packages:
resolution: {integrity: sha512-lmUfT5XcK9KKvt3lLYzn93hc4MGzlUBowExFVgzbSW0ZCrdeyS574dfsyfRhxbg81Wj4gk+RxUiTnj7KBfDA1g==}
dev: true
/jju/1.4.0:
resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
dev: true
/js-tokens/4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
@ -3608,6 +3718,14 @@ packages:
resolution: {integrity: sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=}
dev: true
/lodash.get/4.4.2:
resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
dev: true
/lodash.isequal/4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
dev: true
/lodash.ismatch/4.4.0:
resolution: {integrity: sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=}
dev: true
@ -4815,6 +4933,19 @@ packages:
deprecated: https://github.com/lydell/resolve-url#deprecated
dev: true
/resolve/1.17.0:
resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==}
dependencies:
path-parse: 1.0.7
dev: true
/resolve/1.19.0:
resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==}
dependencies:
is-core-module: 2.9.0
path-parse: 1.0.7
dev: true
/resolve/1.22.0:
resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==}
hasBin: true
@ -5242,6 +5373,10 @@ packages:
readable-stream: 3.6.0
dev: true
/sprintf-js/1.0.3:
resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=}
dev: true
/ssri/6.0.2:
resolution: {integrity: sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==}
dependencies:
@ -5413,6 +5548,11 @@ packages:
engines: {node: '>=8'}
dev: true
/strip-json-comments/3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
dev: true
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@ -5535,6 +5675,10 @@ packages:
setimmediate: 1.0.5
dev: true
/timsort/0.3.0:
resolution: {integrity: sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=}
dev: true
/tinypool/0.1.3:
resolution: {integrity: sha512-2IfcQh7CP46XGWGGbdyO4pjcKqsmVqFAPcXfPxcPXmOWt9cYkTP9HcDmGgsfijYoAEc4z9qcpM/BaBz46Y9/CQ==}
engines: {node: '>=14.0.0'}
@ -5862,6 +6006,11 @@ packages:
spdx-expression-parse: 3.0.1
dev: true
/validator/13.7.0:
resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==}
engines: {node: '>= 0.10'}
dev: true
/vary/1.1.2:
resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=}
engines: {node: '>= 0.8'}
@ -6234,3 +6383,15 @@ packages:
normalize-path: 1.0.0
strip-indent: 2.0.0
dev: true
/z-schema/5.0.3:
resolution: {integrity: sha512-sGvEcBOTNum68x9jCpCVGPFJ6mWnkD0YxOcddDlJHRx3tKdB2q8pCHExMVZo/AV/6geuVJXG7hljDaWG8+5GDw==}
engines: {node: '>=8.0.0'}
hasBin: true
dependencies:
lodash.get: 4.4.2
lodash.isequal: 4.5.0
validator: 13.7.0
optionalDependencies:
commander: 2.20.3
dev: true

View File

@ -1,3 +1,5 @@
import { ASTElementHandler, ASTElementHandlers } from 'typescript/compiler'
const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/
const fnInvokeRE = /\([^)]*?\);*$/
const simplePathRE =

View File

@ -3,6 +3,16 @@ import baseDirectives from '../directives/index'
import { camelize, no, extend } from 'shared/util'
import { baseWarn, pluckModuleFunction } from '../helpers'
import { emptySlotScopeToken } from '../parser/index'
import {
ASTAttr,
ASTDirective,
ASTElement,
ASTExpression,
ASTIfConditions,
ASTNode,
ASTText,
CompilerOptions
} from 'typescript/compiler'
type TransformFunction = (el: ASTElement, code: string) => string
type DataGenFunction = (el: ASTElement) => string

View File

@ -1,4 +1,9 @@
import { extend } from 'shared/util'
import {
CompilerOptions,
CompiledResult,
WarningMessage
} from 'typescript/compiler'
import { detectErrors } from './error-detector'
import { createCompileToFunctionFn } from './to-function'

View File

@ -1,3 +1,5 @@
import { ASTDirective, ASTElement } from 'typescript/compiler'
export default function bind(el: ASTElement, dir: ASTDirective) {
el.wrapData = (code: string) => {
return `_b(${code},'${el.tag}',${dir.value},${

View File

@ -1,3 +1,5 @@
import { ASTElement, ASTModifiers } from 'typescript/compiler'
/**
* Cross-platform code generation for component v-model
*/

View File

@ -1,4 +1,5 @@
import { warn } from 'core/util/index'
import { ASTDirective, ASTElement } from 'typescript/compiler'
export default function on(el: ASTElement, dir: ASTDirective) {
if (__DEV__ && dir.modifiers) {

View File

@ -1,3 +1,4 @@
import { ASTElement, ASTNode } from 'typescript/compiler'
import { dirRE, onRE } from './parser/index'
type Range = { start?: number; end?: number }

View File

@ -1,4 +1,5 @@
import { emptyObject } from 'shared/util'
import { ASTElement, ASTModifiers } from 'typescript/compiler'
import { parseFilters } from './parser/filter-parser'
type Range = { start?: number; end?: number }

View File

@ -2,6 +2,7 @@ import { parse } from './parser/index'
import { optimize } from './optimizer'
import { generate } from './codegen/index'
import { createCompilerCreator } from './create-compiler'
import { CompilerOptions, CompiledResult } from 'typescript/compiler'
// `createCompilerCreator` allows creating compilers that use alternative
// parser/optimizer/codegen, e.g the SSR optimizing compiler.

View File

@ -1,4 +1,5 @@
import { makeMap, isBuiltInTag, cached, no } from 'shared/util'
import { ASTElement, CompilerOptions, ASTNode } from 'typescript/compiler'
let isStaticKey
let isPlatformReservedTag

View File

@ -19,6 +19,15 @@ import {
getAndRemoveAttrByRegex
} from '../helpers'
import {
ASTAttr,
ASTElement,
ASTIfCondition,
ASTNode,
ASTText,
CompilerOptions
} from 'typescript/compiler'
export const onRE = /^@|^v-on:/
export const dirRE = process.env.VBIND_PROP_SHORTHAND
? /^v-|^@|^:|^\.|^#/

View File

@ -2,6 +2,7 @@ import { noop, extend } from 'shared/util'
import { warn as baseWarn, tip } from 'core/util/debug'
import { generateCodeFrame } from './codeframe'
import type { Component } from 'typescript/component'
import { CompilerOptions } from 'typescript/compiler'
type CompiledFunctionResult = {
render: Function

View File

@ -3,6 +3,9 @@ import { no, noop, identity } from 'shared/util'
import { LIFECYCLE_HOOKS } from 'shared/constants'
import type { Component } from 'typescript/component'
/**
* @internal
*/
export interface Config {
// user
optionMergeStrategies: { [key: string]: Function }

View File

@ -9,7 +9,7 @@ import { initProvide, initInjections } from './inject'
import { extend, mergeOptions, formatComponentName } from '../util/index'
import type { Component } from 'typescript/component'
import type { InternalComponentOptions } from 'typescript/options'
import { EffectScope } from 'v3'
import { EffectScope } from 'v3/reactivity/effectScope'
let uid = 0

View File

@ -1,36 +1,22 @@
import { remove } from '../util/index'
import config from '../config'
import { TrackOpTypes, TriggerOpTypes } from 'v3'
import { DebuggerOptions, DebuggerEventExtraInfo } from 'v3'
let uid = 0
/**
* @internal
*/
export interface DepTarget extends DebuggerOptions {
id: number
addDep(dep: Dep): void
update(): void
}
export interface DebuggerOptions {
onTrack?: (event: DebuggerEvent) => void
onTrigger?: (event: DebuggerEvent) => void
}
export type DebuggerEvent = {
effect: DepTarget
} & DebuggerEventExtraInfo
export type DebuggerEventExtraInfo = {
target: object
type: TrackOpTypes | TriggerOpTypes
key?: any
newValue?: any
oldValue?: any
oldTarget?: Map<any, any> | Set<any>
}
/**
* A dep is an observable that can have multiple
* directives subscribing to it.
* @internal
*/
export default class Dep {
static target?: DepTarget | null

View File

@ -12,23 +12,18 @@ import {
import { traverse } from './traverse'
import { queueWatcher } from './scheduler'
import Dep, {
pushTarget,
popTarget,
DepTarget,
DebuggerEvent,
DebuggerOptions
} from './dep'
import Dep, { pushTarget, popTarget, DepTarget } from './dep'
import { DebuggerEvent, DebuggerOptions } from 'v3/debug'
import type { SimpleSet } from '../util/index'
import type { Component } from 'typescript/component'
import {
activeEffectScope,
recordEffectScope
} from '../../v3/reactivity/effectScope'
import { activeEffectScope, recordEffectScope } from 'v3/reactivity/effectScope'
let uid = 0
/**
* @internal
*/
export interface WatcherOptions extends DebuggerOptions {
deep?: boolean
user?: boolean
@ -41,6 +36,7 @@ export interface WatcherOptions extends DebuggerOptions {
* A watcher parses an expression, collects dependencies,
* and fires callback when the expression value changes.
* This is used for both the $watch() api and directives.
* @internal
*/
export default class Watcher implements DepTarget {
vm?: Component | null

View File

@ -87,6 +87,9 @@ if (typeof Promise !== 'undefined' && isNative(Promise)) {
export function nextTick(): Promise<void>
export function nextTick(cb: (...args: any[]) => any, ctx?: object): void
/**
* @internal
*/
export function nextTick(cb?: (...args: any[]) => any, ctx?: object) {
let _resolve
callbacks.push(() => {

View File

@ -2,6 +2,9 @@ import type { Component } from 'typescript/component'
import type { ComponentOptions } from 'typescript/options'
import type { VNodeComponentOptions, VNodeData } from 'typescript/vnode'
/**
* @internal
*/
export default class VNode {
tag?: string
data: VNodeData | undefined

View File

@ -1,4 +1,5 @@
import { addProp } from 'compiler/helpers'
import { ASTDirective, ASTElement } from 'typescript/compiler'
export default function html(el: ASTElement, dir: ASTDirective) {
if (dir.value) {

View File

@ -1,6 +1,7 @@
import config from 'core/config'
import { addHandler, addProp, getBindingAttr } from 'compiler/helpers'
import { genComponentModel, genAssignmentCode } from 'compiler/directives/model'
import { ASTDirective, ASTElement, ASTModifiers } from 'typescript/compiler'
let warn

View File

@ -1,4 +1,5 @@
import { addProp } from 'compiler/helpers'
import { ASTDirective, ASTElement } from 'typescript/compiler'
export default function text(el: ASTElement, dir: ASTDirective) {
if (dir.value) {

View File

@ -1,5 +1,6 @@
import { parseText } from 'compiler/parser/text-parser'
import { getAndRemoveAttr, getBindingAttr, baseWarn } from 'compiler/helpers'
import { ASTElement, CompilerOptions, ModuleOptions } from 'typescript/compiler'
function transformNode(el: ASTElement, options: CompilerOptions) {
const warn = options.warn || baseWarn

View File

@ -16,6 +16,7 @@ import {
addIfCondition,
createASTElement
} from 'compiler/parser/index'
import { ASTElement, CompilerOptions, ModuleOptions } from 'typescript/compiler'
function preTransformNode(el: ASTElement, options: CompilerOptions) {
if (el.tag === 'input') {

View File

@ -1,6 +1,7 @@
import { parseText } from 'compiler/parser/text-parser'
import { parseStyleText } from 'web/util/style'
import { getAndRemoveAttr, getBindingAttr, baseWarn } from 'compiler/helpers'
import { ASTElement, CompilerOptions, ModuleOptions } from 'typescript/compiler'
function transformNode(el: ASTElement, options: CompilerOptions) {
const warn = options.warn || baseWarn

View File

@ -9,6 +9,7 @@ import modules from './modules/index'
import directives from './directives/index'
import { genStaticKeys } from 'shared/util'
import { isUnaryTag, canBeLeftOpenTag } from './util'
import { CompilerOptions } from 'typescript/compiler'
export const baseOptions: CompilerOptions = {
expectHTML: true,

View File

@ -23,6 +23,7 @@ import {
import { escape } from 'web/server/util'
import { optimizability } from './optimizer'
import type { CodegenResult } from 'compiler/codegen/index'
import { ASTElement, ASTNode, CompilerOptions } from 'typescript/compiler'
export type StringSegment = {
type: number

View File

@ -2,6 +2,7 @@ import { parse } from 'compiler/parser/index'
import { generate } from './codegen'
import { optimize } from './optimizer'
import { createCompilerCreator } from 'compiler/create-compiler'
import { CompiledResult, CompilerOptions } from 'typescript/compiler'
export const createCompiler = createCompilerCreator(function baseCompile(
template: string,

View File

@ -10,6 +10,7 @@ import { isBooleanAttr, isEnumeratedAttr } from 'web/util/attrs'
import type { StringSegment } from './codegen'
import type { CodegenState } from 'compiler/codegen/index'
import { ASTAttr, ASTElement } from 'typescript/compiler'
const plainStringRE = /^"(?:[^"\\]|\\.)*"$|^'(?:[^'\\]|\\.)*'$/

View File

@ -9,6 +9,7 @@
*/
import { no, makeMap, isBuiltInTag } from 'shared/util'
import { ASTElement, ASTNode, CompilerOptions } from 'typescript/compiler'
// optimizability constants
export const optimizability = {

View File

@ -1,6 +1,12 @@
import deindent from 'de-indent'
import { parseHTML } from 'compiler/parser/html-parser'
import { makeMap } from 'shared/util'
import {
ASTAttr,
SFCBlock,
SFCDescriptor,
WarningMessage
} from 'typescript/compiler'
const splitRE = /\r?\n/g
const replaceRE = /./g

View File

@ -276,7 +276,9 @@ export const identity = (_: any) => _
/**
* Generate a string containing static keys from compiler modules.
*/
export function genStaticKeys(modules: Array<ModuleOptions>): string {
export function genStaticKeys(
modules: Array<{ staticKeys?: string[] } /* ModuleOptions */>
): string {
return modules
.reduce((keys, m) => {
return keys.concat(m.staticKeys || [])

View File

@ -1,12 +1,12 @@
import { DebuggerEvent } from '.'
import { Component } from '../../typescript/component'
import { DebuggerEvent } from './debug'
import { Component } from 'typescript/component'
import { mergeLifecycleHook, warn } from '../core/util'
import { currentInstance } from './currentInstance'
function createLifeCycle<T extends (...args: any[]) => any = () => void>(
hookName: string
) {
return (fn: T, target: Component | null = currentInstance) => {
return (fn: T, target: any = currentInstance) => {
if (!target) {
__DEV__ &&
warn(

View File

@ -138,10 +138,16 @@ export function syncSetupSlots(to: any, from: any) {
}
}
/**
* @internal use manual type def
*/
export function useSlots(): SetupContext['slots'] {
return getContext().slots
}
/**
* @internal use manual type def
*/
export function useAttrs(): SetupContext['attrs'] {
return getContext().attrs
}

View File

@ -15,7 +15,7 @@ import { currentInstance } from './currentInstance'
import { traverse } from 'core/observer/traverse'
import Watcher from '../core/observer/watcher'
import { queueWatcher } from '../core/observer/scheduler'
import { DebuggerOptions } from '../core/observer/dep'
import { DebuggerOptions } from './debug'
const WATCHER = `watcher`
const WATCHER_CB = `${WATCHER} callback`

View File

@ -6,7 +6,7 @@ export let currentInstance: Component | null = null
* This is exposed for compatibility with v3 (e.g. some functions in VueUse
* relies on it). Do not use this internally, just use `currentInstance`.
*
* @private this function needs manual type declaration because it relies
* @internal this function needs manual type declaration because it relies
* on previously manually authored types from Vue 2
*/
export function getCurrentInstance(): { proxy: Component } | null {
@ -14,7 +14,7 @@ export function getCurrentInstance(): { proxy: Component } | null {
}
/**
* @private
* @internal
*/
export function setCurrentInstance(vm: Component | null = null) {
if (!vm) currentInstance && currentInstance._scope.off()

21
src/v3/debug.ts Normal file
View File

@ -0,0 +1,21 @@
import { TrackOpTypes, TriggerOpTypes } from './reactivity/operations'
export interface DebuggerOptions {
onTrack?: (event: DebuggerEvent) => void
onTrigger?: (event: DebuggerEvent) => void
}
export type DebuggerEvent = {
/**
* @internal
*/
effect: any
} & DebuggerEventExtraInfo
export type DebuggerEventExtraInfo = {
target: object
type: TrackOpTypes | TriggerOpTypes
key?: any
newValue?: any
oldValue?: any
}

View File

@ -3,7 +3,7 @@ import { currentInstance } from './currentInstance'
import { warn } from 'core/util'
/**
* @private this function needs manual public type declaration because it relies
* @internal this function needs manual public type declaration because it relies
* on previously manually authored types from Vue 2
*/
export function h(type: any, props?: any, children?: any) {

View File

@ -62,11 +62,8 @@ export {
getCurrentScope
} from './reactivity/effectScope'
export {
DebuggerOptions,
DebuggerEvent,
DebuggerEventExtraInfo
} from 'core/observer/dep'
export { DebuggerOptions, DebuggerEvent, DebuggerEventExtraInfo } from './debug'
export { TrackOpTypes, TriggerOpTypes } from './reactivity/operations'
export { provide, inject, InjectionKey } from './apiInject'
@ -74,6 +71,6 @@ export { provide, inject, InjectionKey } from './apiInject'
export { h } from './h'
export { getCurrentInstance } from './currentInstance'
export { useSlots, useAttrs } from './apiSetup'
export { nextTick } from 'core/util'
export { nextTick } from 'core/util/next-tick'
export * from './apiLifecycle'

View File

@ -1,10 +1,11 @@
import { isServerRendering, noop, warn, def, isFunction } from 'core/util'
import { Ref, RefFlag } from './ref'
import Watcher from 'core/observer/watcher'
import Dep, { DebuggerOptions } from 'core/observer/dep'
import Dep from 'core/observer/dep'
import { currentInstance } from '../currentInstance'
import { ReactiveFlags } from './reactive'
import { TrackOpTypes } from './operations'
import { DebuggerOptions } from '../debug'
declare const ComputedRefSymbol: unique symbol
@ -14,7 +15,7 @@ export interface ComputedRef<T = any> extends WritableComputedRef<T> {
}
export interface WritableComputedRef<T> extends Ref<T> {
readonly effect: Watcher
readonly effect: any /* Watcher */
}
export type ComputedGetter<T> = (...args: any[]) => T

View File

@ -5,7 +5,7 @@ import { currentInstance } from '../currentInstance'
// export type EffectScheduler = (...args: any[]) => any
/**
* @private since we are not exposing this in Vue 2, it's used only for
* @internal since we are not exposing this in Vue 2, it's used only for
* internal testing.
*/
export function effect(fn: () => any, scheduler?: (cb: any) => void) {

View File

@ -106,6 +106,9 @@ export function effectScope(detached?: boolean) {
return new EffectScope(detached)
}
/**
* @internal
*/
export function recordEffectScope(
effect: Watcher,
scope: EffectScope | undefined = activeEffectScope

View File

@ -113,7 +113,7 @@ export function markRaw<T extends object>(
}
/**
* @private
* @internal
*/
export function isCollectionType(value: unknown): boolean {
const type = toRawType(value)

View File

@ -12,6 +12,9 @@ import { TrackOpTypes, TriggerOpTypes } from './operations'
declare const RefSymbol: unique symbol
export declare const RawSymbol: unique symbol
/**
* @internal
*/
export const RefFlag = `__v_isRef`
export interface Ref<T = any> {
@ -23,11 +26,11 @@ export interface Ref<T = any> {
*/
[RefSymbol]: true
/**
* @private
* @internal
*/
dep?: Dep
/**
* @private
* @internal
*/
[RefFlag]: true
}
@ -203,7 +206,9 @@ export function toRef<T extends object, K extends keyof T>(
* augmentations in its generated d.ts, so we have to manually append them
* to the final generated d.ts in our build process.
*/
export interface RefUnwrapBailTypes {}
export interface RefUnwrapBailTypes {
runtimeDOMBailTypes: Node | Window
}
export type ShallowUnwrapRef<T> = {
[K in keyof T]: T[K] extends Ref<infer V>

3
types/index.d.ts vendored
View File

@ -32,4 +32,5 @@ export {
VNodeDirective
} from './vnode'
export { h, getCurrentInstance } from './v3'
export * from './v3'
export * from './v3-generated'

14
types/test/utils.ts Normal file
View File

@ -0,0 +1,14 @@
export declare function describe(_name: string, _fn: () => void): void
export declare function test(_name: string, _fn: () => any): void
export declare function expectType<T>(value: T): void
export declare function expectError<T>(value: T): void
export declare function expectAssignable<T, T2 extends T = T>(value: T2): void
export type IsUnion<T, U extends T = T> = (
T extends any ? (U extends T ? false : true) : never
) extends false
? false
: true
export type IsAny<T> = 0 extends 1 & T ? true : false

View File

@ -0,0 +1,16 @@
import { InjectionKey, provide, inject } from '../../index'
import { expectType } from '../utils'
const key: InjectionKey<number> = Symbol()
provide(key, 1)
// @ts-expect-error
provide(key, 'foo')
expectType<number | undefined>(inject(key))
expectType<number>(inject(key, 1))
expectType<number>(inject(key, () => 1, true /* treatDefaultAsFactory */))
expectType<() => number>(inject('foo', () => 1))
expectType<() => number>(inject('foo', () => 1, false))
expectType<number>(inject('foo', () => 1, true))

View File

@ -0,0 +1,373 @@
import {
Ref,
ref,
shallowRef,
isRef,
unref,
reactive,
toRef,
toRefs,
ToRefs,
shallowReactive,
readonly,
markRaw,
shallowReadonly
} from '../../index'
import { describe, expectType } from '../utils'
function plainType(arg: number | Ref<number>) {
// ref coercing
const coerced = ref(arg)
expectType<Ref<number>>(coerced)
// isRef as type guard
if (isRef(arg)) {
expectType<Ref<number>>(arg)
}
// ref unwrapping
expectType<number>(unref(arg))
// ref inner type should be unwrapped
const nestedRef = ref({
foo: ref(1)
})
expectType<{ foo: number }>(nestedRef.value)
// ref boolean
const falseRef = ref(false)
expectType<Ref<boolean>>(falseRef)
expectType<boolean>(falseRef.value)
// ref true
const trueRef = ref<true>(true)
expectType<Ref<true>>(trueRef)
expectType<true>(trueRef.value)
// tuple
expectType<[number, string]>(unref(ref([1, '1'])))
interface IteratorFoo {
[Symbol.iterator]: any
}
// with symbol
expectType<Ref<IteratorFoo | null | undefined>>(
ref<IteratorFoo | null | undefined>()
)
// should not unwrap ref inside arrays
const arr = ref([1, new Map<string, any>(), ref('1')]).value
const value = arr[0]
if (isRef(value)) {
expectType<Ref>(value)
} else if (typeof value === 'number') {
expectType<number>(value)
} else {
// should narrow down to Map type
// and not contain any Ref type
expectType<Map<string, any>>(value)
}
// should still unwrap in objects nested in arrays
const arr2 = ref([{ a: ref(1) }]).value
expectType<number>(arr2[0].a)
}
plainType(1)
function bailType(arg: HTMLElement | Ref<HTMLElement>) {
// ref coercing
const coerced = ref(arg)
expectType<Ref<HTMLElement>>(coerced)
// isRef as type guard
if (isRef(arg)) {
expectType<Ref<HTMLElement>>(arg)
}
// ref unwrapping
expectType<HTMLElement>(unref(arg))
// ref inner type should be unwrapped
// eslint-disable-next-line no-restricted-globals
const nestedRef = ref({ foo: ref(document.createElement('DIV')) })
expectType<Ref<{ foo: HTMLElement }>>(nestedRef)
expectType<{ foo: HTMLElement }>(nestedRef.value)
}
// eslint-disable-next-line no-restricted-globals
const el = document.createElement('DIV')
bailType(el)
function withSymbol() {
const customSymbol = Symbol()
const obj = {
[Symbol.asyncIterator]: ref(1),
[Symbol.hasInstance]: { a: ref('a') },
[Symbol.isConcatSpreadable]: { b: ref(true) },
[Symbol.iterator]: [ref(1)],
[Symbol.match]: new Set<Ref<number>>(),
[Symbol.matchAll]: new Map<number, Ref<string>>(),
[Symbol.replace]: { arr: [ref('a')] },
[Symbol.search]: { set: new Set<Ref<number>>() },
[Symbol.species]: { map: new Map<number, Ref<string>>() },
[Symbol.split]: new WeakSet<Ref<boolean>>(),
[Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),
[Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },
[Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },
[customSymbol]: { arr: [ref(1)] }
}
const objRef = ref(obj)
expectType<Ref<number>>(objRef.value[Symbol.asyncIterator])
expectType<{ a: Ref<string> }>(objRef.value[Symbol.hasInstance])
expectType<{ b: Ref<boolean> }>(objRef.value[Symbol.isConcatSpreadable])
expectType<Ref<number>[]>(objRef.value[Symbol.iterator])
expectType<Set<Ref<number>>>(objRef.value[Symbol.match])
expectType<Map<number, Ref<string>>>(objRef.value[Symbol.matchAll])
expectType<{ arr: Ref<string>[] }>(objRef.value[Symbol.replace])
expectType<{ set: Set<Ref<number>> }>(objRef.value[Symbol.search])
expectType<{ map: Map<number, Ref<string>> }>(objRef.value[Symbol.species])
expectType<WeakSet<Ref<boolean>>>(objRef.value[Symbol.split])
expectType<WeakMap<Ref<boolean>, string>>(objRef.value[Symbol.toPrimitive])
expectType<{ weakSet: WeakSet<Ref<boolean>> }>(
objRef.value[Symbol.toStringTag]
)
expectType<{ weakMap: WeakMap<Ref<boolean>, string> }>(
objRef.value[Symbol.unscopables]
)
expectType<{ arr: Ref<number>[] }>(objRef.value[customSymbol])
}
withSymbol()
const state = reactive({
foo: {
value: 1,
label: 'bar'
}
})
expectType<string>(state.foo.label)
// shallowRef
type Status = 'initial' | 'ready' | 'invalidating'
const shallowStatus = shallowRef<Status>('initial')
if (shallowStatus.value === 'initial') {
expectType<Ref<Status>>(shallowStatus)
expectType<Status>(shallowStatus.value)
shallowStatus.value = 'invalidating'
}
const refStatus = ref<Status>('initial')
if (refStatus.value === 'initial') {
expectType<Ref<Status>>(shallowStatus)
expectType<Status>(shallowStatus.value)
refStatus.value = 'invalidating'
}
// proxyRefs: should return `reactive` directly
// const r1 = reactive({
// k: 'v'
// })
// const p1 = proxyRefs(r1)
// expectType<typeof r1>(p1)
// // proxyRefs: `ShallowUnwrapRef`
// const r2 = {
// a: ref(1),
// obj: {
// k: ref('foo')
// }
// }
// const p2 = proxyRefs(r2)
// expectType<number>(p2.a)
// expectType<Ref<string>>(p2.obj.k)
// toRef and toRefs
{
const obj: {
a: number
b: Ref<number>
c: number | string
} = {
a: 1,
b: ref(1),
c: 1
}
// toRef
expectType<Ref<number>>(toRef(obj, 'a'))
expectType<Ref<number>>(toRef(obj, 'b'))
// Should not distribute Refs over union
expectType<Ref<number | string>>(toRef(obj, 'c'))
// toRefs
expectType<{
a: Ref<number>
b: Ref<number>
// Should not distribute Refs over union
c: Ref<number | string>
}>(toRefs(obj))
// Both should not do any unwrapping
const someReactive = shallowReactive({
a: {
b: ref(42)
}
})
const toRefResult = toRef(someReactive, 'a')
const toRefsResult = toRefs(someReactive)
expectType<Ref<number>>(toRefResult.value.b)
expectType<Ref<number>>(toRefsResult.a.value.b)
// #5188
const props = { foo: 1 } as { foo: any }
const { foo } = toRefs(props)
expectType<Ref<any>>(foo)
}
// toRef default value
{
const obj: { x?: number } = {}
const x = toRef(obj, 'x', 1)
expectType<Ref<number>>(x)
}
// readonly() + ref()
expectType<Readonly<Ref<number>>>(readonly(ref(1)))
// #2687
interface AppData {
state: 'state1' | 'state2' | 'state3'
}
const data: ToRefs<AppData> = toRefs(
reactive({
state: 'state1'
})
)
switch (data.state.value) {
case 'state1':
data.state.value = 'state2'
break
case 'state2':
data.state.value = 'state3'
break
case 'state3':
data.state.value = 'state1'
break
}
// #3954
function testUnrefGenerics<T>(p: T | Ref<T>) {
expectType<T>(unref(p))
}
testUnrefGenerics(1)
// #4771
describe('shallow reactive in reactive', () => {
const baz = reactive({
foo: shallowReactive({
a: {
b: ref(42)
}
})
})
const foo = toRef(baz, 'foo')
expectType<Ref<number>>(foo.value.a.b)
expectType<number>(foo.value.a.b.value)
})
describe('shallow ref in reactive', () => {
const x = reactive({
foo: shallowRef({
bar: {
baz: ref(123),
qux: reactive({
z: ref(123)
})
}
})
})
expectType<Ref<number>>(x.foo.bar.baz)
expectType<number>(x.foo.bar.qux.z)
})
describe('ref in shallow ref', () => {
const x = shallowRef({
a: ref(123)
})
expectType<Ref<number>>(x.value.a)
})
describe('reactive in shallow ref', () => {
const x = shallowRef({
a: reactive({
b: ref(0)
})
})
expectType<number>(x.value.a.b)
})
describe('should support DeepReadonly', () => {
const r = readonly({ obj: { k: 'v' } })
// @ts-expect-error
expectError((r.obj = {}))
// @ts-expect-error
expectError((r.obj.k = 'x'))
})
// #4180
describe('readonly ref', () => {
const r = readonly(ref({ count: 1 }))
expectType<Ref>(r)
})
describe('should support markRaw', () => {
class Test<T> {
item = {} as Ref<T>
}
const test = new Test<number>()
const plain = {
ref: ref(1)
}
const r = reactive({
class: {
raw: markRaw(test),
reactive: test
},
plain: {
raw: markRaw(plain),
reactive: plain
}
})
expectType<Test<number>>(r.class.raw)
// @ts-expect-error it should unwrap
expectType<Test<number>>(r.class.reactive)
expectType<Ref<number>>(r.plain.raw.ref)
// @ts-expect-error it should unwrap
expectType<Ref<number>>(r.plain.reactive.ref)
})
describe('shallowReadonly ref unwrap', () => {
const r = shallowReadonly({ count: { n: ref(1) } })
// @ts-expect-error
r.count = 2
expectType<Ref>(r.count.n)
r.count.n.value = 123
})

View File

@ -1,4 +1,4 @@
import Vue from '../index'
import Vue from '../../index'
// object props
Vue.extend({
@ -28,8 +28,5 @@ Vue.extend({
}
ctx.emit('foo')
ctx.slots.default && ctx.slots.default()
ctx.expose({
foo: 123
})
}
})

View File

@ -0,0 +1,78 @@
import { ref, computed, watch } from '../../index'
import { expectType } from '../utils'
const source = ref('foo')
const source2 = computed(() => source.value)
const source3 = () => 1
// lazy watcher will have consistent types for oldValue.
watch(source, (value, oldValue) => {
expectType<string>(value)
expectType<string>(oldValue)
})
watch([source, source2, source3], (values, oldValues) => {
expectType<[string, string, number]>(values)
expectType<[string, string, number]>(oldValues)
})
// const array
watch([source, source2, source3] as const, (values, oldValues) => {
expectType<Readonly<[string, string, number]>>(values)
expectType<Readonly<[string, string, number]>>(oldValues)
})
// immediate watcher's oldValue will be undefined on first run.
watch(
source,
(value, oldValue) => {
expectType<string>(value)
expectType<string | undefined>(oldValue)
},
{ immediate: true }
)
watch(
[source, source2, source3],
(values, oldValues) => {
expectType<[string, string, number]>(values)
expectType<[string | undefined, string | undefined, number | undefined]>(
oldValues
)
},
{ immediate: true }
)
// const array
watch(
[source, source2, source3] as const,
(values, oldValues) => {
expectType<Readonly<[string, string, number]>>(values)
expectType<
Readonly<[string | undefined, string | undefined, number | undefined]>
>(oldValues)
},
{ immediate: true }
)
// should provide correct ref.value inner type to callbacks
const nestedRefSource = ref({
foo: ref(1)
})
watch(nestedRefSource, (v, ov) => {
expectType<{ foo: number }>(v)
expectType<{ foo: number }>(ov)
})
const someRef = ref({ test: 'test' })
const otherRef = ref({ a: 'b' })
watch([someRef, otherRef], values => {
const value1 = values[0]
// no type error
console.log(value1.test)
const value2 = values[1]
// no type error
console.log(value2.a)
})

View File

@ -1,10 +1,10 @@
{
"compilerOptions": {
"target": "es5",
"target": "esnext",
"experimentalDecorators": true,
"lib": ["dom", "es2015"],
"lib": ["dom", "esnext"],
"types": ["node"],
"module": "commonjs",
"module": "esnext",
"strict": true,
"noEmit": true,
"baseUrl": ".",

4
types/v3.d.ts vendored
View File

@ -10,3 +10,7 @@ export interface SetupContext {
export function getCurrentInstance(): { proxy: Vue } | null
export const h: CreateElement
export function useAttrs(): SetupContext['attrs']
export function useSlots(): SetupContext['slots']

View File

@ -1,4 +1,4 @@
declare type CompilerOptions = {
export type CompilerOptions = {
warn?: Function // allow customizing warning in different environments; e.g. node
modules?: Array<ModuleOptions> // platform specific modules; e.g. style; class
directives?: { [key: string]: Function } // platform specific directives
@ -29,13 +29,13 @@ declare type CompilerOptions = {
scopeId?: string
}
declare type WarningMessage = {
export type WarningMessage = {
msg: string
start?: number
end?: number
}
declare type CompiledResult = {
export type CompiledResult = {
ast: ASTElement | null
render: string
staticRenderFns: Array<string>
@ -44,7 +44,7 @@ declare type CompiledResult = {
tips?: Array<string | WarningMessage>
}
declare type ModuleOptions = {
export type ModuleOptions = {
// transform an AST node before any attributes are processed
// returning an ASTElement from pre/transforms replaces the element
preTransformNode: (el: ASTElement) => ASTElement | null
@ -58,11 +58,11 @@ declare type ModuleOptions = {
staticKeys?: Array<string> // AST properties to be considered static
}
declare type ASTModifiers = { [key: string]: boolean }
declare type ASTIfCondition = { exp: string | null; block: ASTElement }
declare type ASTIfConditions = Array<ASTIfCondition>
export type ASTModifiers = { [key: string]: boolean }
export type ASTIfCondition = { exp: string | null; block: ASTElement }
export type ASTIfConditions = Array<ASTIfCondition>
declare type ASTAttr = {
export type ASTAttr = {
name: string
value: any
dynamic?: boolean
@ -70,7 +70,7 @@ declare type ASTAttr = {
end?: number
}
declare type ASTElementHandler = {
export type ASTElementHandler = {
value: string
params?: Array<any>
modifiers: ASTModifiers | null
@ -79,11 +79,11 @@ declare type ASTElementHandler = {
end?: number
}
declare type ASTElementHandlers = {
export type ASTElementHandlers = {
[key: string]: ASTElementHandler | Array<ASTElementHandler>
}
declare type ASTDirective = {
export type ASTDirective = {
name: string
rawName: string
value: string
@ -94,9 +94,9 @@ declare type ASTDirective = {
end?: number
}
declare type ASTNode = ASTElement | ASTText | ASTExpression
export type ASTNode = ASTElement | ASTText | ASTExpression
declare type ASTElement = {
export type ASTElement = {
type: 1
tag: string
attrsList: Array<ASTAttr>
@ -177,7 +177,7 @@ declare type ASTElement = {
ssrOptimizability?: number
}
declare type ASTExpression = {
export type ASTExpression = {
type: 2
expression: string
text: string
@ -189,7 +189,7 @@ declare type ASTExpression = {
end?: number
}
declare type ASTText = {
export type ASTText = {
type: 3
text: string
static?: boolean
@ -203,7 +203,7 @@ declare type ASTText = {
// SFC-parser related declarations
// an object format describing a single-file component
declare type SFCDescriptor = {
export type SFCDescriptor = {
template: SFCBlock | null
script: SFCBlock | null
styles: Array<SFCBlock>
@ -211,7 +211,7 @@ declare type SFCDescriptor = {
errors: Array<string | WarningMessage>
}
declare type SFCBlock = {
export type SFCBlock = {
type: string
content: string
attrs: { [attribute: string]: string }

View File

@ -3,10 +3,13 @@ import type Watcher from '../src/core/observer/watcher'
import { ComponentOptions, SetupContext } from './options'
import { ScopedSlotsData, VNodeChildren, VNodeData } from './vnode'
import { GlobalAPI } from './global-api'
import { EffectScope } from 'v3'
import { EffectScope } from 'v3/reactivity/effectScope'
// TODO this should be using the same as /component/
/**
* @internal
*/
export declare class Component {
constructor(options?: any)
// constructor information

View File

@ -1,7 +1,10 @@
import { Config } from '../src/core/config'
import { Component } from './component'
declare interface GlobalAPI {
/**
* @internal
*/
export interface GlobalAPI {
// new(options?: any): Component
(options?: any): void
cid: number

View File

@ -2,7 +2,7 @@ import VNode from '../src/core/vdom/vnode'
import { DebuggerEvent } from '../src/v3'
import { Component } from './component'
declare type InternalComponentOptions = {
export type InternalComponentOptions = {
_isComponent: true
parent: Component
_parentVnode: VNode
@ -12,13 +12,19 @@ declare type InternalComponentOptions = {
type InjectKey = string | Symbol
declare interface SetupContext {
/**
* @internal
*/
export interface SetupContext {
attrs: Record<string, any>
slots: Record<string, () => VNode[]>
emit: (event: string, ...args: any[]) => any
}
declare type ComponentOptions = {
/**
* @internal
*/
export type ComponentOptions = {
// v3
setup?: (props: Record<string, any>, ctx: SetupContext) => unknown
@ -106,7 +112,7 @@ declare type ComponentOptions = {
_base: typeof Component
}
declare type PropOptions = {
export type PropOptions = {
type: Function | Array<Function> | null
default: any
required: boolean | null

View File

@ -1,14 +1,14 @@
import VNode from '../src/core/vdom/vnode'
import { Component } from './component'
declare type ComponentWithCacheContext = {
export type ComponentWithCacheContext = {
type: 'ComponentWithCache'
bufferIndex: number
buffer: Array<string>
key: string
}
declare type ElementContext = {
export type ElementContext = {
type: 'Element'
children: Array<VNode>
rendered: number
@ -16,12 +16,12 @@ declare type ElementContext = {
total: number
}
declare type ComponentContext = {
export type ComponentContext = {
type: 'Component'
prevActive: Component
}
declare type RenderState =
export type RenderState =
| ComponentContext
| ComponentWithCacheContext
| ElementContext

View File

@ -1,12 +1,19 @@
import VNode from '../src/core/vdom/vnode'
import { Ref } from '../src/v3'
import { Component } from './component'
import { ASTModifiers } from './compiler'
declare type VNodeChildren =
/**
* @internal
*/
export type VNodeChildren =
| Array<null | VNode | string | number | VNodeChildren>
| string
declare type VNodeComponentOptions = {
/**
* @internal
*/
export type VNodeComponentOptions = {
Ctor: typeof Component
propsData?: Object
listeners?: Record<string, Function | Function[]>
@ -14,7 +21,10 @@ declare type VNodeComponentOptions = {
tag?: string
}
declare type MountedComponentVNode = VNode & {
/**
* @internal
*/
export type MountedComponentVNode = VNode & {
context: Component
componentOptions: VNodeComponentOptions
componentInstance: Component
@ -22,8 +32,11 @@ declare type MountedComponentVNode = VNode & {
data: VNodeData
}
/**
* @internal
*/
// interface for vnodes in update modules
declare type VNodeWithData = VNode & {
export type VNodeWithData = VNode & {
tag: string
data: VNodeData
children: Array<VNode>
@ -39,7 +52,7 @@ declare type VNodeWithData = VNode & {
}
// // interface for vnodes in update modules
// declare type VNodeWithData = {
// export type VNodeWithData = {
// tag: string;
// data: VNodeData;
// children: Array<VNode>;
@ -54,7 +67,10 @@ declare type VNodeWithData = VNode & {
// isRootInsert: boolean;
// };
declare interface VNodeData {
/**
* @internal
*/
export interface VNodeData {
key?: string | number
slot?: string
ref?: string | Ref | ((el: any) => void)
@ -89,7 +105,10 @@ declare interface VNodeData {
[key: string]: any
}
declare type VNodeDirective = {
/**
* @internal
*/
export type VNodeDirective = {
name: string
rawName: string
value?: any
@ -100,6 +119,9 @@ declare type VNodeDirective = {
def?: Object
}
declare type ScopedSlotsData = Array<
/**
* @internal
*/
export type ScopedSlotsData = Array<
{ key: string; fn: Function } | ScopedSlotsData
>