Skip to content

Commit

Permalink
Merge pull request #37 from vuejs/main
Browse files Browse the repository at this point in the history
sync
  • Loading branch information
encourage317125 authored Jul 11, 2023
2 parents 2d7595e + 2a2810c commit 15fc287
Show file tree
Hide file tree
Showing 44 changed files with 762 additions and 406 deletions.
2 changes: 1 addition & 1 deletion BACKERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Vue.js is an MIT-licensed open source project with its ongoing development made

<p align="center">
<a target="_blank" href="https://sponsors.vuejs.org/backers.svg">
<img alt="sponsors" src="https://sponsors.vuejs.org/backers.svg">
<img alt="sponsors" src="https://sponsors.vuejs.org/backers.svg?v1">
</a>
</p>
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"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-ssr-esm": "node scripts/build.js compiler-sfc server-renderer -f esm-browser",
"build-sfc-playground-self": "cd packages/sfc-playground && npm run build",
"preinstall": "node ./scripts/preinstall.js",
"preinstall": "npx only-allow pnpm",
"postinstall": "simple-git-hooks"
},
"simple-git-hooks": {
Expand Down Expand Up @@ -87,7 +87,7 @@
"prettier": "^2.7.1",
"pug": "^3.0.1",
"puppeteer": "~19.6.0",
"rollup": "^3.20.2",
"rollup": "^3.26.0",
"rollup-plugin-dts": "^5.3.0",
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-polyfill-node": "^0.12.0",
Expand All @@ -97,7 +97,7 @@
"terser": "^5.15.1",
"todomvc-app-css": "^2.3.0",
"tslib": "^2.5.0",
"typescript": "^5.0.0",
"typescript": "^5.1.6",
"vite": "^4.3.0",
"vitest": "^0.30.1"
}
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-dom/src/decodeHtmlBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export function decodeHtmlBrowser(raw: string, asAttr = false): string {
}
if (asAttr) {
decoder.innerHTML = `<div foo="${raw.replace(/"/g, '&quot;')}">`
return decoder.children[0].getAttribute('foo') as string
return decoder.children[0].getAttribute('foo')!
} else {
decoder.innerHTML = raw
return decoder.textContent as string
return decoder.textContent!
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,21 @@ return { get vMyDir() { return vMyDir } }
})"
`;
exports[`SFC compile <script setup> > dev mode import usage check > dynamic arguments 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { FooBar, foo, bar, unused } from './x'
export default /*#__PURE__*/_defineComponent({
setup(__props, { expose: __expose }) {
__expose();
return { get FooBar() { return FooBar }, get foo() { return foo }, get bar() { return bar } }
}
})"
`;
exports[`SFC compile <script setup> > dev mode import usage check > js template string interpolations 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { VAR, VAR2, VAR3 } from './x'
Expand Down Expand Up @@ -775,6 +790,21 @@ return { get FooBaz() { return FooBaz }, get Last() { return Last } }
})"
`;
exports[`SFC compile <script setup> > dev mode import usage check > template ref 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { foo, bar, Baz } from './foo'
export default /*#__PURE__*/_defineComponent({
setup(__props, { expose: __expose }) {
__expose();
return { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }
}
})"
`;
exports[`SFC compile <script setup> > dev mode import usage check > vue interpolations 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { x, y, z, x$y } from './x'
Expand Down
36 changes: 36 additions & 0 deletions packages/compiler-sfc/__tests__/compileScript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,25 @@ describe('SFC compile <script setup>', () => {
assertCode(content)
})

test('dynamic arguments', () => {
const { content } = compile(`
<script setup lang="ts">
import { FooBar, foo, bar, unused } from './x'
</script>
<template>
<FooBar #[foo.slotName] />
<FooBar #unused />
<div :[bar.attrName]="15"></div>
<div unused="unused"></div>
</template>
`)
expect(content).toMatch(
`return { get FooBar() { return FooBar }, get foo() { return foo }, ` +
`get bar() { return bar } }`
)
assertCode(content)
})

// https://github.com/vuejs/core/issues/4599
test('attribute expressions', () => {
const { content } = compile(`
Expand Down Expand Up @@ -513,6 +532,23 @@ describe('SFC compile <script setup>', () => {
</template>
`)
})

test('template ref', () => {
const { content } = compile(`
<script setup lang="ts">
import { foo, bar, Baz } from './foo'
</script>
<template>
<div ref="foo"></div>
<div ref=""></div>
<Baz ref="bar" />
</template>
`)
expect(content).toMatch(
'return { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }'
)
assertCode(content)
})
})

describe('inlineTemplate mode', () => {
Expand Down
9 changes: 9 additions & 0 deletions packages/compiler-sfc/src/script/importUsageCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,22 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
if (!isBuiltInDirective(prop.name)) {
code += `,v${capitalize(camelize(prop.name))}`
}
if (prop.arg && !(prop.arg as SimpleExpressionNode).isStatic) {
code += `,${processExp(
(prop.arg as SimpleExpressionNode).content,
prop.name
)}`
}
if (prop.exp) {
code += `,${processExp(
(prop.exp as SimpleExpressionNode).content,
prop.name
)}`
}
}
if (prop.type === NodeTypes.ATTRIBUTE && prop.name === 'ref' && prop.value?.content) {
code += `,${prop.value.content}`
}
}
} else if (node.type === NodeTypes.INTERPOLATION) {
code += `,${processExp(
Expand Down
5 changes: 3 additions & 2 deletions packages/compiler-sfc/src/style/cssVars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ export function parseCssVars(sfc: SFCDescriptor): string[] {
const vars: string[] = []
sfc.styles.forEach(style => {
let match
// ignore v-bind() in comments /* ... */
const content = style.content.replace(/\/\*([\s\S]*?)\*\//g, '')
// ignore v-bind() in comments, eg /* ... */
// and // (Less, Sass and Stylus all support the use of // to comment)
const content = style.content.replace(/\/\*([\s\S]*?)\*\/|\/\/.*/g, '')
while ((match = vBindRE.exec(content))) {
const start = match.index + match[0].length
const end = lexBinding(content, start)
Expand Down
5 changes: 3 additions & 2 deletions packages/compiler-sfc/src/style/pluginScoped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,10 @@ function rewriteSelector(
// DEPRECATED usage
// .foo ::v-deep .bar -> .foo[xxxxxxx] .bar
warn(
`::v-deep usage as a combinator has ` +
`been deprecated. Use :deep(<inner-selector>) instead.`
`${value} usage as a combinator has been deprecated. ` +
`Use :deep(<inner-selector>) instead of ${value} <inner-selector>.`
)

const prev = selector.at(selector.index(n) - 1)
if (prev && isSpaceCombinator(prev)) {
selector.removeChild(prev)
Expand Down
3 changes: 1 addition & 2 deletions packages/compiler-sfc/src/style/preprocessors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ const less: StylePreprocessor = (source, map, options, load = require) => {
const styl: StylePreprocessor = (source, map, options, load = require) => {
const nodeStylus = load('stylus')
try {
const ref = nodeStylus(source)
Object.keys(options).forEach(key => ref.set(key, options[key]))
const ref = nodeStylus(source, options)
if (map) ref.set('sourcemap', { inline: false, comment: false })

const result = ref.render()
Expand Down
38 changes: 38 additions & 0 deletions packages/compiler-ssr/__tests__/ssrVModel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,44 @@ describe('ssr: v-model', () => {
`)
})

test('<select v-model>', () => {
expect(
compileWithWrapper(
`<select v-model="model"><option value="1"></option></select>`
).code
).toMatchInlineSnapshot(`
"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent, _attrs) {
_push(\`<div\${
_ssrRenderAttrs(_attrs)
}><select><option value=\\"1\\"\${
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
? _ssrLooseContain(_ctx.model, \\"1\\")
: _ssrLooseEqual(_ctx.model, \\"1\\"))) ? \\" selected\\" : \\"\\"
}></option></select></div>\`)
}"
`)

expect(
compileWithWrapper(
`<select multiple v-model="model"><option value="1" selected></option><option value="2"></option></select>`
).code
).toMatchInlineSnapshot(`
"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent, _attrs) {
_push(\`<div\${
_ssrRenderAttrs(_attrs)
}><select multiple><option value=\\"1\\" selected></option><option value=\\"2\\"\${
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
? _ssrLooseContain(_ctx.model, \\"2\\")
: _ssrLooseEqual(_ctx.model, \\"2\\"))) ? \\" selected\\" : \\"\\"
}></option></select></div>\`)
}"
`)
})

test('<input type="radio">', () => {
expect(
compileWithWrapper(`<input type="radio" value="foo" v-model="bar">`).code
Expand Down
33 changes: 30 additions & 3 deletions packages/compiler-ssr/src/transforms/ssrVModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
import {
SSR_LOOSE_EQUAL,
SSR_LOOSE_CONTAIN,
SSR_RENDER_DYNAMIC_MODEL
SSR_RENDER_DYNAMIC_MODEL,
SSR_INCLUDE_BOOLEAN_ATTR
} from '../runtimeHelpers'
import { DirectiveTransformResult } from 'packages/compiler-core/src/transform'

Expand Down Expand Up @@ -129,8 +130,34 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
checkDuplicatedValue()
node.children = [createInterpolation(model, model.loc)]
} else if (node.tag === 'select') {
// NOOP
// select relies on client-side directive to set initial selected state.
node.children.forEach(option => {
if (option.type === NodeTypes.ELEMENT) {
const plainNode = option as PlainElementNode
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
const value = findValueBinding(plainNode)
plainNode.ssrCodegenNode!.elements.push(
createConditionalExpression(
createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [
createConditionalExpression(
createCallExpression(`Array.isArray`, [model]),
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
model,
value
]),
createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
model,
value
])
)
]),
createSimpleExpression(' selected', true),
createSimpleExpression('', true),
false /* no newline */
)
)
}
}
})
} else {
context.onError(
createDOMCompilerError(
Expand Down
2 changes: 1 addition & 1 deletion packages/dts-test/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1363,13 +1363,13 @@ describe('function syntax w/ runtime props', () => {
}
)

// @ts-expect-error prop type mismatch
defineComponent(
(_props: { msg: string }) => {
return () => {}
},
{
props: {
// @ts-expect-error prop type mismatch
msg: Number
}
}
Expand Down
20 changes: 20 additions & 0 deletions packages/dts-test/setupHelpers.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ describe('defineProps w/ generic type declaration + withDefaults', <T extends nu
expectType<boolean>(res.bool)
})

describe('withDefaults w/ boolean type', () => {
const res1 = withDefaults(
defineProps<{
bool?: boolean
}>(),
{ bool: false }
)
expectType<boolean>(res1.bool)

const res2 = withDefaults(
defineProps<{
bool?: boolean
}>(),
{
bool: undefined
}
)
expectType<boolean | undefined>(res2.bool)
})

describe('defineProps w/ runtime declaration', () => {
// runtime declaration
const props = defineProps({
Expand Down
5 changes: 2 additions & 3 deletions packages/reactivity/__tests__/computed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,13 @@ describe('reactivity/computed', () => {
const onTrigger = vi.fn((e: DebuggerEvent) => {
events.push(e)
})
const obj = reactive({ foo: 1 })
const obj = reactive<{ foo?: number }>({ foo: 1 })
const c = computed(() => obj.foo, { onTrigger })

// computed won't trigger compute until accessed
c.value

obj.foo++
obj.foo!++
expect(c.value).toBe(2)
expect(onTrigger).toHaveBeenCalledTimes(1)
expect(events[0]).toEqual({
Expand All @@ -277,7 +277,6 @@ describe('reactivity/computed', () => {
newValue: 2
})

// @ts-ignore
delete obj.foo
expect(c.value).toBeUndefined()
expect(onTrigger).toHaveBeenCalledTimes(2)
Expand Down
7 changes: 5 additions & 2 deletions packages/reactivity/__tests__/reactive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('reactivity/reactive', () => {
const reactiveObj = reactive(obj)
expect(isReactive(reactiveObj)).toBe(true)
// read prop of reactiveObject will cause reactiveObj[prop] to be reactive
// @ts-ignore
// @ts-expect-error
const prototype = reactiveObj['__proto__']
const otherObj = { data: ['a'] }
expect(isReactive(otherObj)).toBe(false)
Expand Down Expand Up @@ -204,7 +204,7 @@ describe('reactivity/reactive', () => {
const dummy = computed(() => observed.a)
expect(dummy.value).toBe(0)

// @ts-ignore
// @ts-expect-error
observed.a = bar
expect(dummy.value).toBe(1)

Expand Down Expand Up @@ -233,6 +233,9 @@ describe('reactivity/reactive', () => {
// symbol
const s = Symbol()
assertValue(s)
// bigint
const bn = BigInt('9007199254740991')
assertValue(bn)

// built-ins should work and return same value
const p = Promise.resolve()
Expand Down
Loading

0 comments on commit 15fc287

Please sign in to comment.