Skip to content

Commit 3013572

Browse files
authored
Merge branch 'minor' into bwsy/feat/compilerSearchElm
2 parents 3b41769 + c6083dc commit 3013572

File tree

8 files changed

+183
-23
lines changed

8 files changed

+183
-23
lines changed

packages/compiler-core/__tests__/transforms/vBind.spec.ts

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,60 @@ describe('compiler: transform v-bind', () => {
7272
})
7373
})
7474

75+
test('no expression', () => {
76+
const node = parseWithVBind(`<div v-bind:id />`)
77+
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
78+
expect(props.properties[0]).toMatchObject({
79+
key: {
80+
content: `id`,
81+
isStatic: true,
82+
loc: {
83+
start: {
84+
line: 1,
85+
column: 13,
86+
offset: 12
87+
},
88+
end: {
89+
line: 1,
90+
column: 15,
91+
offset: 14
92+
}
93+
}
94+
},
95+
value: {
96+
content: `id`,
97+
isStatic: false,
98+
loc: {
99+
start: {
100+
line: 1,
101+
column: 1,
102+
offset: 0
103+
},
104+
end: {
105+
line: 1,
106+
column: 1,
107+
offset: 0
108+
}
109+
}
110+
}
111+
})
112+
})
113+
114+
test('no expression (shorthand)', () => {
115+
const node = parseWithVBind(`<div :id />`)
116+
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
117+
expect(props.properties[0]).toMatchObject({
118+
key: {
119+
content: `id`,
120+
isStatic: true
121+
},
122+
value: {
123+
content: `id`,
124+
isStatic: false
125+
}
126+
})
127+
})
128+
75129
test('dynamic arg', () => {
76130
const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
77131
const props = (node.codegenNode as VNodeCall).props as CallExpression
@@ -98,9 +152,9 @@ describe('compiler: transform v-bind', () => {
98152
})
99153
})
100154

101-
test('should error if no expression', () => {
155+
test('should error if empty expression', () => {
102156
const onError = vi.fn()
103-
const node = parseWithVBind(`<div v-bind:arg />`, { onError })
157+
const node = parseWithVBind(`<div v-bind:arg="" />`, { onError })
104158
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
105159
expect(onError.mock.calls[0][0]).toMatchObject({
106160
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
@@ -111,7 +165,7 @@ describe('compiler: transform v-bind', () => {
111165
},
112166
end: {
113167
line: 1,
114-
column: 16
168+
column: 19
115169
}
116170
}
117171
})
@@ -142,6 +196,21 @@ describe('compiler: transform v-bind', () => {
142196
})
143197
})
144198

199+
test('.camel modifier w/ no expression', () => {
200+
const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)
201+
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
202+
expect(props.properties[0]).toMatchObject({
203+
key: {
204+
content: `fooBar`,
205+
isStatic: true
206+
},
207+
value: {
208+
content: `fooBar`,
209+
isStatic: false
210+
}
211+
})
212+
})
213+
145214
test('.camel modifier w/ dynamic arg', () => {
146215
const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
147216
const props = (node.codegenNode as VNodeCall).props as CallExpression
@@ -219,6 +288,21 @@ describe('compiler: transform v-bind', () => {
219288
})
220289
})
221290

291+
test('.prop modifier w/ no expression', () => {
292+
const node = parseWithVBind(`<div v-bind:fooBar.prop />`)
293+
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
294+
expect(props.properties[0]).toMatchObject({
295+
key: {
296+
content: `.fooBar`,
297+
isStatic: true
298+
},
299+
value: {
300+
content: `fooBar`,
301+
isStatic: false
302+
}
303+
})
304+
})
305+
222306
test('.prop modifier w/ dynamic arg', () => {
223307
const node = parseWithVBind(`<div v-bind:[fooBar].prop="id"/>`)
224308
const props = (node.codegenNode as VNodeCall).props as CallExpression
@@ -296,6 +380,21 @@ describe('compiler: transform v-bind', () => {
296380
})
297381
})
298382

383+
test('.prop modifier (shortband) w/ no expression', () => {
384+
const node = parseWithVBind(`<div .fooBar />`)
385+
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
386+
expect(props.properties[0]).toMatchObject({
387+
key: {
388+
content: `.fooBar`,
389+
isStatic: true
390+
},
391+
value: {
392+
content: `fooBar`,
393+
isStatic: false
394+
}
395+
})
396+
})
397+
299398
test('.attr modifier', () => {
300399
const node = parseWithVBind(`<div v-bind:foo-bar.attr="id"/>`)
301400
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
@@ -310,4 +409,19 @@ describe('compiler: transform v-bind', () => {
310409
}
311410
})
312411
})
412+
413+
test('.attr modifier w/ no expression', () => {
414+
const node = parseWithVBind(`<div v-bind:foo-bar.attr />`)
415+
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
416+
expect(props.properties[0]).toMatchObject({
417+
key: {
418+
content: `^foo-bar`,
419+
isStatic: true
420+
},
421+
value: {
422+
content: `fooBar`,
423+
isStatic: false
424+
}
425+
})
426+
})
313427
})

packages/compiler-core/src/transforms/vBind.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@ import {
33
createObjectProperty,
44
createSimpleExpression,
55
ExpressionNode,
6+
locStub,
67
NodeTypes
78
} from '../ast'
89
import { createCompilerError, ErrorCodes } from '../errors'
910
import { camelize } from '@vue/shared'
1011
import { CAMELIZE } from '../runtimeHelpers'
12+
import { processExpression } from './transformExpression'
1113

1214
// v-bind without arg is handled directly in ./transformElements.ts due to it affecting
1315
// codegen for the entire props object. This transform here is only for v-bind
1416
// *with* args.
1517
export const transformBind: DirectiveTransform = (dir, _node, context) => {
16-
const { exp, modifiers, loc } = dir
18+
const { modifiers, loc } = dir
1719
const arg = dir.arg!
1820

1921
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) {
@@ -46,6 +48,18 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
4648
}
4749
}
4850

51+
// :arg is replaced by :arg="arg"
52+
let { exp } = dir
53+
if (!exp && arg.type === NodeTypes.SIMPLE_EXPRESSION) {
54+
const propName = camelize(arg.loc.source)
55+
const simpleExpression = createSimpleExpression(propName, false, {
56+
...locStub,
57+
source: propName
58+
})
59+
60+
exp = dir.exp = processExpression(simpleExpression, context)
61+
}
62+
4963
if (
5064
!exp ||
5165
(exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())

packages/compiler-sfc/__tests__/__snapshots__/compileTemplate.spec.ts.snap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ exports[`source map 1`] = `
7979
exports[`template errors 1`] = `
8080
[
8181
[SyntaxError: Error parsing JavaScript expression: Unexpected token (1:3)],
82-
[SyntaxError: v-bind is missing expression.],
8382
[SyntaxError: v-model can only be used on <input>, <textarea> and <select> elements.],
8483
]
8584
`;

packages/compiler-sfc/__tests__/compileStyle.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ describe('SFC scoped CSS', () => {
8585
".baz .qux[data-v-test] .foo .bar { color: red;
8686
}"
8787
`)
88+
expect(compileScoped(`:is(.foo :deep(.bar)) { color: red; }`))
89+
.toMatchInlineSnapshot(`
90+
":is(.foo[data-v-test] .bar) { color: red;
91+
}"
92+
`)
93+
expect(compileScoped(`:where(.foo :deep(.bar)) { color: red; }`))
94+
.toMatchInlineSnapshot(`
95+
":where(.foo[data-v-test] .bar) { color: red;
96+
}"
97+
`)
8898
})
8999

90100
test('::v-slotted', () => {

packages/compiler-sfc/__tests__/compileTemplate.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ test('source map', () => {
124124
test('template errors', () => {
125125
const result = compile({
126126
filename: 'example.vue',
127-
source: `<div :foo
127+
source: `<div
128128
:bar="a[" v-model="baz"/>`
129129
})
130130
expect(result.errors).toMatchSnapshot()

packages/compiler-sfc/src/style/pluginScoped.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ function rewriteSelector(
173173
if (n.type !== 'pseudo' && n.type !== 'combinator') {
174174
node = n
175175
}
176+
177+
if (n.type === 'pseudo' && (n.value === ':is' || n.value === ':where')) {
178+
rewriteSelector(id, n.nodes[0], selectorRoot, slotted)
179+
shouldInject = false
180+
}
176181
})
177182

178183
if (node) {

packages/reactivity/src/computed.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export interface WritableComputedRef<T> extends Ref<T> {
1616
readonly effect: ReactiveEffect<T>
1717
}
1818

19-
export type ComputedGetter<T> = (...args: any[]) => T
20-
export type ComputedSetter<T> = (v: T) => void
19+
export type ComputedGetter<T> = (oldValue?: T) => T
20+
export type ComputedSetter<T> = (newValue: T) => void
2121

2222
export interface WritableComputedOptions<T> {
2323
get: ComputedGetter<T>
@@ -41,9 +41,10 @@ export class ComputedRefImpl<T> {
4141
isReadonly: boolean,
4242
isSSR: boolean
4343
) {
44-
this.effect = new ReactiveEffect(getter, () => {
45-
triggerRefValue(this, DirtyLevels.ComputedValueMaybeDirty)
46-
})
44+
this.effect = new ReactiveEffect(
45+
() => getter(this._value),
46+
() => triggerRefValue(this, DirtyLevels.ComputedValueMaybeDirty)
47+
)
4748
this.effect.computed = this
4849
this.effect.active = this._cacheable = !isSSR
4950
this[ReactiveFlags.IS_READONLY] = isReadonly

scripts/release.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,23 @@ async function main() {
270270

271271
// publish packages
272272
step('\nPublishing packages...')
273+
274+
const additionalPublishFlags = []
275+
if (isDryRun) {
276+
additionalPublishFlags.push('--dry-run')
277+
}
278+
if (skipGit) {
279+
additionalPublishFlags.push('--no-git-checks')
280+
}
281+
// bypass the pnpm --publish-branch restriction which isn't too useful to us
282+
// otherwise it leads to a prompt and blocks the release script
283+
const branch = await getBranch()
284+
if (branch !== 'main') {
285+
additionalPublishFlags.push('--publish-branch', branch)
286+
}
287+
273288
for (const pkg of packages) {
274-
await publishPackage(pkg, targetVersion)
289+
await publishPackage(pkg, targetVersion, additionalPublishFlags)
275290
}
276291

277292
// push to GitHub
@@ -300,7 +315,7 @@ async function main() {
300315

301316
async function getCIResult() {
302317
try {
303-
const { stdout: sha } = await execa('git', ['rev-parse', 'HEAD'])
318+
const sha = await getSha()
304319
const res = await fetch(
305320
`https://api.github.com/repos/vuejs/core/actions/runs?head_sha=${sha}` +
306321
`&status=success&exclude_pull_requests=true`
@@ -315,17 +330,12 @@ async function getCIResult() {
315330

316331
async function isInSyncWithRemote() {
317332
try {
318-
const { stdout: sha } = await execa('git', ['rev-parse', 'HEAD'])
319-
const { stdout: branch } = await execa('git', [
320-
'rev-parse',
321-
'--abbrev-ref',
322-
'HEAD'
323-
])
333+
const branch = await getBranch()
324334
const res = await fetch(
325335
`https://api.github.com/repos/vuejs/core/commits/${branch}?per_page=1`
326336
)
327337
const data = await res.json()
328-
return data.sha === sha
338+
return data.sha === (await getSha())
329339
} catch (e) {
330340
console.error(
331341
'Failed to check whether local HEAD is up-to-date with remote.'
@@ -334,6 +344,14 @@ async function isInSyncWithRemote() {
334344
}
335345
}
336346

347+
async function getSha() {
348+
return (await execa('git', ['rev-parse', 'HEAD'])).stdout
349+
}
350+
351+
async function getBranch() {
352+
return (await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'])).stdout
353+
}
354+
337355
function updateVersions(version, getNewPackageName = keepThePackageName) {
338356
// 1. update root package.json
339357
updatePackage(path.resolve(__dirname, '..'), version, getNewPackageName)
@@ -371,7 +389,7 @@ function updateDeps(pkg, depType, version, getNewPackageName) {
371389
})
372390
}
373391

374-
async function publishPackage(pkgName, version) {
392+
async function publishPackage(pkgName, version, additionalFlags) {
375393
if (skippedPackages.includes(pkgName)) {
376394
return
377395
}
@@ -402,8 +420,7 @@ async function publishPackage(pkgName, version) {
402420
...(releaseTag ? ['--tag', releaseTag] : []),
403421
'--access',
404422
'public',
405-
...(isDryRun ? ['--dry-run'] : []),
406-
...(skipGit ? ['--no-git-checks'] : [])
423+
...additionalFlags
407424
],
408425
{
409426
cwd: pkgRoot,

0 commit comments

Comments
 (0)