Skip to content

Commit 5a42b3c

Browse files
authored
Merge branch 'vuejs:main' into bwsy/transformElm
2 parents 564dbab + bcfe480 commit 5a42b3c

File tree

21 files changed

+155
-96
lines changed

21 files changed

+155
-96
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,24 @@ describe('compiler: v-if', () => {
628628
expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` }))
629629
})
630630

631+
// #6631
632+
test('avoid duplicate keys', () => {
633+
const {
634+
node: { codegenNode }
635+
} = parseWithIfTransform(`<div v-if="ok" key="custom_key" v-bind="obj"/>`)
636+
const branch1 = codegenNode.consequent as VNodeCall
637+
expect(branch1.props).toMatchObject({
638+
type: NodeTypes.JS_CALL_EXPRESSION,
639+
callee: MERGE_PROPS,
640+
arguments: [
641+
createObjectMatcher({
642+
key: 'custom_key'
643+
}),
644+
{ content: `obj` }
645+
]
646+
})
647+
})
648+
631649
test('with spaces between branches', () => {
632650
const {
633651
node: { codegenNode }

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,21 @@ describe('compiler: transform v-on', () => {
271271
})
272272
})
273273

274+
test('should NOT wrap as function if expression is already function expression (with Typescript)', () => {
275+
const { node } = parseWithVOn(`<div @click="(e: any): any => foo(e)"/>`)
276+
expect((node.codegenNode as VNodeCall).props).toMatchObject({
277+
properties: [
278+
{
279+
key: { content: `onClick` },
280+
value: {
281+
type: NodeTypes.SIMPLE_EXPRESSION,
282+
content: `(e: any): any => foo(e)`
283+
}
284+
}
285+
]
286+
})
287+
})
288+
274289
test('should NOT wrap as function if expression is already function expression (with newlines)', () => {
275290
const { node } = parseWithVOn(
276291
`<div @click="

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { hasScopeRef, isMemberExpression } from '../utils'
1717
import { TO_HANDLER_KEY } from '../runtimeHelpers'
1818

1919
const fnExpRE =
20-
/^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/
20+
/^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/
2121

2222
export interface VOnDirectiveNode extends DirectiveNode {
2323
// v-on without arg is handled directly in ./transformElements.ts due to it affecting

packages/compiler-core/src/utils.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,10 @@ export function injectProp(
397397
// if doesn't override user provided keys
398398
const first = props.arguments[0] as string | JSChildNode
399399
if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) {
400-
first.properties.unshift(prop)
400+
// #6631
401+
if (!hasProp(prop, first)) {
402+
first.properties.unshift(prop)
403+
}
401404
} else {
402405
if (props.callee === TO_HANDLERS) {
403406
// #2366
@@ -411,17 +414,7 @@ export function injectProp(
411414
}
412415
!propsWithInjection && (propsWithInjection = props)
413416
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
414-
let alreadyExists = false
415-
// check existing key to avoid overriding user provided keys
416-
if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {
417-
const propKeyName = prop.key.content
418-
alreadyExists = props.properties.some(
419-
p =>
420-
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
421-
p.key.content === propKeyName
422-
)
423-
}
424-
if (!alreadyExists) {
417+
if (!hasProp(prop, props)) {
425418
props.properties.unshift(prop)
426419
}
427420
propsWithInjection = props
@@ -453,6 +446,20 @@ export function injectProp(
453446
}
454447
}
455448

449+
// check existing key to avoid overriding user provided keys
450+
function hasProp(prop: Property, props: ObjectExpression) {
451+
let result = false
452+
if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {
453+
const propKeyName = prop.key.content
454+
result = props.properties.some(
455+
p =>
456+
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
457+
p.key.content === propKeyName
458+
)
459+
}
460+
return result
461+
}
462+
456463
export function toValidAssetId(
457464
name: string,
458465
type: 'component' | 'directive' | 'filter'

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ export default {
640640
setup(__props, { expose }) {
641641
expose();
642642

643-
const props = __props
643+
const props = __props;
644644

645645

646646

@@ -658,7 +658,7 @@ export default {
658658
setup(__props, { expose }) {
659659
expose();
660660

661-
const props = __props
661+
const props = __props;
662662

663663

664664
return { props, x }
@@ -675,7 +675,7 @@ exports[`SFC compile <script setup> defineProps() 1`] = `
675675
setup(__props, { expose }) {
676676
expose();
677677

678-
const props = __props
678+
const props = __props;
679679

680680

681681
const bar = 1
@@ -693,7 +693,7 @@ exports[`SFC compile <script setup> defineProps/defineEmits in multi-variable de
693693
setup(__props, { expose, emit }) {
694694
expose();
695695

696-
const props = __props
696+
const props = __props;
697697

698698

699699

@@ -710,7 +710,7 @@ exports[`SFC compile <script setup> defineProps/defineEmits in multi-variable de
710710
setup(__props, { expose, emit }) {
711711
expose();
712712

713-
const props = __props
713+
const props = __props;
714714

715715
const a = 1;
716716

@@ -1611,7 +1611,7 @@ export default /*#__PURE__*/_defineComponent({
16111611
setup(__props, { expose, emit }) {
16121612
expose();
16131613

1614-
const props = __props
1614+
const props = __props;
16151615

16161616

16171617

@@ -1705,7 +1705,7 @@ const props = __props as {
17051705
foo?: string
17061706
bar?: number
17071707
baz: boolean
1708-
}
1708+
};
17091709

17101710

17111711

@@ -1728,7 +1728,7 @@ export default /*#__PURE__*/_defineComponent({
17281728
setup(__props: any, { expose }) {
17291729
expose();
17301730

1731-
const props = __props as { foo: string, bar?: number, baz: boolean, qux(): number }
1731+
const props = __props as { foo: string, bar?: number, baz: boolean, qux(): number };
17321732

17331733

17341734

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ exports[`sfc props transform $$() escape 1`] = `
66
export default {
77
props: ['foo'],
88
setup(__props) {
9-
const __props_bar = _toRef(__props, 'bar')
10-
const __props_foo = _toRef(__props, 'foo')
9+
const __props_bar = _toRef(__props, 'bar');
10+
const __props_foo = _toRef(__props, 'foo');
1111
1212
1313
console.log((__props_foo))
@@ -160,7 +160,7 @@ export default {
160160
props: ['foo', 'bar', 'baz'],
161161
setup(__props) {
162162
163-
const rest = _createPropsRestProxy(__props, [\\"foo\\",\\"bar\\"])
163+
const rest = _createPropsRestProxy(__props, [\\"foo\\",\\"bar\\"]);
164164
165165
166166

packages/compiler-sfc/src/compileScript.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,15 +1411,15 @@ export function compileScript(
14111411
startOffset,
14121412
`\nconst ${propsIdentifier} = __props${
14131413
propsTypeDecl ? ` as ${genSetupPropsType(propsTypeDecl)}` : ``
1414-
}\n`
1414+
};\n`
14151415
)
14161416
}
14171417
if (propsDestructureRestId) {
14181418
s.prependLeft(
14191419
startOffset,
14201420
`\nconst ${propsDestructureRestId} = ${helper(
14211421
`createPropsRestProxy`
1422-
)}(__props, ${JSON.stringify(Object.keys(propsDestructuredBindings))})\n`
1422+
)}(__props, ${JSON.stringify(Object.keys(propsDestructuredBindings))});\n`
14231423
)
14241424
}
14251425
// inject temp variables for async context preservation

packages/compiler-sfc/src/parse.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,8 @@ export interface SFCScriptBlock extends SFCBlock {
4444
setup?: string | boolean
4545
bindings?: BindingMetadata
4646
imports?: Record<string, ImportBinding>
47-
/**
48-
* import('\@babel/types').Statement
49-
*/
50-
scriptAst?: any[]
51-
/**
52-
* import('\@babel/types').Statement
53-
*/
54-
scriptSetupAst?: any[]
47+
scriptAst?: import('@babel/types').Statement[]
48+
scriptSetupAst?: import('@babel/types').Statement[]
5549
}
5650

5751
export interface SFCStyleBlock extends SFCBlock {

packages/reactivity-transform/__tests__/__snapshots__/reactivityTransform.spec.ts.snap

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ exports[`array destructure 1`] = `
6161
6262
let n = _ref(1), __$temp_1 = (useFoo()),
6363
a = _toRef(__$temp_1, 0),
64-
b = _toRef(__$temp_1, 1, 1)
64+
b = _toRef(__$temp_1, 1, 1);
6565
console.log(n.value, a.value, b.value)
6666
"
6767
`;
@@ -90,7 +90,7 @@ exports[`macro import alias and removal 1`] = `
9090
let a = _ref(1)
9191
const __$temp_1 = (useMouse()),
9292
x = _toRef(__$temp_1, 'x'),
93-
y = _toRef(__$temp_1, 'y')
93+
y = _toRef(__$temp_1, 'y');
9494
"
9595
`;
9696
@@ -130,10 +130,10 @@ exports[`nested destructure 1`] = `
130130
"import { toRef as _toRef } from 'vue'
131131
132132
let __$temp_1 = (useFoo()),
133-
b = _toRef(__$temp_1[0].a, 'b')
133+
b = _toRef(__$temp_1[0].a, 'b');
134134
let __$temp_2 = (useBar()),
135135
d = _toRef(__$temp_2.c, 0),
136-
e = _toRef(__$temp_2.c, 1)
136+
e = _toRef(__$temp_2.c, 1);
137137
console.log(b.value, d.value, e.value)
138138
"
139139
`;
@@ -183,9 +183,9 @@ exports[`object destructure 1`] = `
183183
c = _toRef(__$temp_1, 'b'),
184184
d = _toRef(__$temp_1, 'd', 1),
185185
f = _toRef(__$temp_1, 'e', 2),
186-
h = _toRef(__$temp_1, g)
186+
h = _toRef(__$temp_1, g);
187187
let __$temp_2 = (useSomething(() => 1)),
188-
foo = _toRef(__$temp_2, 'foo');
188+
foo = _toRef(__$temp_2, 'foo');;
189189
console.log(n.value, a.value, c.value, d.value, f.value, h.value, foo.value)
190190
"
191191
`;
@@ -194,7 +194,7 @@ exports[`object destructure w/ mid-path default values 1`] = `
194194
"import { toRef as _toRef } from 'vue'
195195
196196
const __$temp_1 = (useFoo()),
197-
b = _toRef((__$temp_1.a || { b: 123 }), 'b')
197+
b = _toRef((__$temp_1.a || { b: 123 }), 'b');
198198
console.log(b.value)
199199
"
200200
`;

packages/reactivity-transform/src/reactivityTransform.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ export function transformAST(
321321
s.overwrite(pattern.start! + offset, pattern.end! + offset, tempVar)
322322
}
323323

324+
let nameId: Identifier | undefined
324325
for (const p of pattern.properties) {
325-
let nameId: Identifier | undefined
326326
let key: Expression | string | undefined
327327
let defaultValue: Expression | undefined
328328
if (p.type === 'ObjectProperty') {
@@ -391,6 +391,9 @@ export function transformAST(
391391
)
392392
}
393393
}
394+
if (nameId) {
395+
s.appendLeft(call.end! + offset, ';')
396+
}
394397
}
395398

396399
function processRefArrayPattern(
@@ -405,10 +408,10 @@ export function transformAST(
405408
s.overwrite(pattern.start! + offset, pattern.end! + offset, tempVar)
406409
}
407410

411+
let nameId: Identifier | undefined
408412
for (let i = 0; i < pattern.elements.length; i++) {
409413
const e = pattern.elements[i]
410414
if (!e) continue
411-
let nameId: Identifier | undefined
412415
let defaultValue: Expression | undefined
413416
if (e.type === 'Identifier') {
414417
// [a] --> [__a]
@@ -438,6 +441,9 @@ export function transformAST(
438441
)
439442
}
440443
}
444+
if (nameId) {
445+
s.appendLeft(call.end! + offset, ';')
446+
}
441447
}
442448

443449
type PathSegmentAtom = Expression | string | number
@@ -545,7 +551,7 @@ export function transformAST(
545551
offset,
546552
`const __props_${publicKey} = ${helper(
547553
`toRef`
548-
)}(__props, '${publicKey}')\n`
554+
)}(__props, '${publicKey}');\n`
549555
)
550556
}
551557
}

packages/reactivity/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export {
2828
shallowReadonly,
2929
markRaw,
3030
toRaw,
31+
Raw,
3132
ReactiveFlags,
3233
DeepReadonly,
3334
ShallowReactive,

packages/reactivity/src/reactive.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ export function toRaw<T>(observed: T): T {
241241
return raw ? toRaw(raw) : observed
242242
}
243243

244-
export function markRaw<T extends object>(
245-
value: T
246-
): T & { [RawSymbol]?: true } {
244+
export type Raw<T> = T & { [RawSymbol]?: true }
245+
246+
export function markRaw<T extends object>(value: T): Raw<T> {
247247
def(value, ReactiveFlags.SKIP, true)
248248
return value
249249
}

packages/runtime-core/__tests__/directives.spec.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ describe('directives', () => {
242242
expect(root.children[0]).toBe(el)
243243

244244
// node should not have been updated yet
245-
// expect(el.children[0].text).toBe(`${count.value - 1}`)
245+
expect(el.children[0].text).toBe(`${count.value - 1}`)
246246

247247
assertBindings(binding)
248248

@@ -421,4 +421,21 @@ describe('directives', () => {
421421
render(h(App), root)
422422
expect(res!).toBe('Test')
423423
})
424+
425+
test('should not throw with unknown directive', async () => {
426+
const d1 = {
427+
mounted: jest.fn()
428+
}
429+
const App = {
430+
name: 'App',
431+
render() {
432+
// simulates the code generated on an unknown directive
433+
return withDirectives(h('div'), [[undefined], [d1]])
434+
}
435+
}
436+
437+
const root = nodeOps.createElement('div')
438+
render(h(App), root)
439+
expect(d1.mounted).toHaveBeenCalled()
440+
})
424441
})

0 commit comments

Comments
 (0)