Skip to content

Commit 7fb6fdd

Browse files
committed
build: introduce feature flags, hide new slot syntax behind flag
1 parent 0cf6aad commit 7fb6fdd

File tree

6 files changed

+156
-142
lines changed

6 files changed

+156
-142
lines changed

Diff for: scripts/config.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const node = require('rollup-plugin-node-resolve')
77
const flow = require('rollup-plugin-flow-no-whitespace')
88
const version = process.env.VERSION || require('../package.json').version
99
const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version
10+
const featureFlags = require('./feature-flags')
1011

1112
const banner =
1213
'/*!\n' +
@@ -241,9 +242,13 @@ function genConfig (name) {
241242
}
242243

243244
if (opts.env) {
244-
config.plugins.push(replace({
245+
const vars = {
245246
'process.env.NODE_ENV': JSON.stringify(opts.env)
246-
}))
247+
}
248+
Object.keys(featureFlags).forEach(key => {
249+
vars[`process.env.${key}`] = featureFlags[key]
250+
})
251+
config.plugins.push(replace(vars))
247252
}
248253

249254
if (opts.transpile !== false) {

Diff for: scripts/feature-flags.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
NEW_SLOT_SYNTAX: false
3+
}

Diff for: src/compiler/parser/index.js

+16-14
Original file line numberDiff line numberDiff line change
@@ -568,22 +568,24 @@ function processSlotContent (el) {
568568
}
569569
el.slotScope = (
570570
slotScope ||
571-
getAndRemoveAttr(el, 'slot-scope') ||
571+
getAndRemoveAttr(el, 'slot-scope')
572+
)
573+
if (process.env.NEW_SLOT_SYNTAX) {
572574
// new in 2.6: slot-props and its shorthand works the same as slot-scope
573575
// when used on <template> containers
574-
getAndRemoveAttr(el, 'slot-props')
575-
)
576-
// 2.6 shorthand syntax
577-
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)
578-
if (shorthand) {
579-
if (process.env.NODE_ENV !== 'production' && el.slotScope) {
580-
warn(
581-
`Unexpected mixed usage of different slot syntaxes.`,
582-
el
583-
)
576+
el.slotScope = el.slotScope || getAndRemoveAttr(el, 'slot-props')
577+
// 2.6 shorthand syntax
578+
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)
579+
if (shorthand) {
580+
if (process.env.NODE_ENV !== 'production' && el.slotScope) {
581+
warn(
582+
`Unexpected mixed usage of different slot syntaxes.`,
583+
el
584+
)
585+
}
586+
el.slotTarget = getScopedSlotShorthandName(shorthand)
587+
el.slotScope = shorthand.value
584588
}
585-
el.slotTarget = getScopedSlotShorthandName(shorthand)
586-
el.slotScope = shorthand.value
587589
}
588590
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
589591
/* istanbul ignore if */
@@ -597,7 +599,7 @@ function processSlotContent (el) {
597599
)
598600
}
599601
el.slotScope = slotScope
600-
} else {
602+
} else if (process.env.NEW_SLOT_SYNTAX) {
601603
// 2.6: slot-props on component, denotes default slot
602604
slotScope = getAndRemoveAttr(el, 'slot-props')
603605
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)

Diff for: src/core/vdom/helpers/normalize-scoped-slots.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function normalizeScopedSlots (
3232
function normalizeScopedSlot(fn: Function): Function {
3333
return scope => {
3434
const res = fn(scope)
35-
return res && typeof res === 'object'
35+
return res && typeof res === 'object' && !Array.isArray(res)
3636
? [res] // single vnode
3737
: normalizeChildren(res)
3838
}

Diff for: test/unit/features/component/component-scoped-slot.spec.js

+126-124
Original file line numberDiff line numberDiff line change
@@ -632,64 +632,116 @@ describe('Component scoped slot', () => {
632632
}).then(done)
633633
})
634634

635-
// new in 2.6
636-
describe('slot-props syntax', () => {
637-
const Foo = {
638-
render(h) {
639-
return h('div', [
640-
this.$scopedSlots.default && this.$scopedSlots.default('from foo default'),
641-
this.$scopedSlots.one && this.$scopedSlots.one('from foo one'),
642-
this.$scopedSlots.two && this.$scopedSlots.two('from foo two')
643-
])
635+
// 2.6 new slot syntax
636+
if (process.env.NEW_SLOT_SYNTAX) {
637+
describe('slot-props syntax', () => {
638+
const Foo = {
639+
render(h) {
640+
return h('div', [
641+
this.$scopedSlots.default && this.$scopedSlots.default('from foo default'),
642+
this.$scopedSlots.one && this.$scopedSlots.one('from foo one'),
643+
this.$scopedSlots.two && this.$scopedSlots.two('from foo two')
644+
])
645+
}
644646
}
645-
}
646647

647-
const Bar = {
648-
render(h) {
649-
return this.$scopedSlots.default && this.$scopedSlots.default('from bar')[0]
648+
const Bar = {
649+
render(h) {
650+
return this.$scopedSlots.default && this.$scopedSlots.default('from bar')
651+
}
650652
}
651-
}
652653

653-
const Baz = {
654-
render(h) {
655-
return this.$scopedSlots.default && this.$scopedSlots.default('from baz')[0]
654+
const Baz = {
655+
render(h) {
656+
return this.$scopedSlots.default && this.$scopedSlots.default('from baz')
657+
}
656658
}
657-
}
658659

659-
function runSuite(syntax) {
660-
it('default slot', () => {
661-
const vm = new Vue({
662-
template: `<foo ${syntax}="foo">{{ foo }}<div>{{ foo }}</div></foo>`,
663-
components: { Foo }
664-
}).$mount()
665-
expect(vm.$el.innerHTML).toBe(`from foo default<div>from foo default</div>`)
666-
})
660+
function runSuite(syntax) {
661+
it('default slot', () => {
662+
const vm = new Vue({
663+
template: `<foo ${syntax}="foo">{{ foo }}<div>{{ foo }}</div></foo>`,
664+
components: { Foo }
665+
}).$mount()
666+
expect(vm.$el.innerHTML).toBe(`from foo default<div>from foo default</div>`)
667+
})
667668

668-
it('nested default slots', () => {
669-
const vm = new Vue({
670-
template: `
671-
<foo ${syntax}="foo">
672-
<bar ${syntax}="bar">
673-
<baz ${syntax}="baz">
674-
{{ foo }} | {{ bar }} | {{ baz }}
675-
</baz>
676-
</bar>
677-
</foo>
678-
`,
679-
components: { Foo, Bar, Baz }
680-
}).$mount()
681-
expect(vm.$el.innerHTML.trim()).toBe(`from foo default | from bar | from baz`)
682-
})
669+
it('nested default slots', () => {
670+
const vm = new Vue({
671+
template: `
672+
<foo ${syntax}="foo">
673+
<bar ${syntax}="bar">
674+
<baz ${syntax}="baz">
675+
{{ foo }} | {{ bar }} | {{ baz }}
676+
</baz>
677+
</bar>
678+
</foo>
679+
`,
680+
components: { Foo, Bar, Baz }
681+
}).$mount()
682+
expect(vm.$el.innerHTML.trim()).toBe(`from foo default | from bar | from baz`)
683+
})
684+
685+
it('default + named slots', () => {
686+
const vm = new Vue({
687+
template: `
688+
<foo ()="foo">
689+
{{ foo }}
690+
<template slot="one" ${syntax}="one">
691+
{{ one }}
692+
</template>
693+
<template slot="two" ${syntax}="two">
694+
{{ two }}
695+
</template>
696+
</foo>
697+
`,
698+
components: { Foo }
699+
}).$mount()
700+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo default from foo one from foo two`)
701+
})
702+
703+
it('nested + named + default slots', () => {
704+
const vm = new Vue({
705+
template: `
706+
<foo>
707+
<template slot="one" ${syntax}="one">
708+
<bar ${syntax}="bar">
709+
{{ one }} {{ bar }}
710+
</bar>
711+
</template>
712+
<template slot="two" ${syntax}="two">
713+
<baz ${syntax}="baz">
714+
{{ two }} {{ baz }}
715+
</baz>
716+
</template>
717+
</foo>
718+
`,
719+
components: { Foo, Bar, Baz }
720+
}).$mount()
721+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one from bar from foo two from baz`)
722+
})
723+
724+
it('should warn slot-props usage on non-component elements', () => {
725+
const vm = new Vue({
726+
template: `<div ${syntax}="foo"/>`
727+
}).$mount()
728+
expect(`slot-props cannot be used on non-component elements`).toHaveBeenWarned()
729+
})
730+
}
731+
732+
// run tests for both full syntax and shorthand
733+
runSuite('slot-props')
734+
runSuite('()')
683735

684-
it('default + named slots', () => {
736+
it('shorthand named slots', () => {
685737
const vm = new Vue({
686738
template: `
687739
<foo ()="foo">
688740
{{ foo }}
689-
<template slot="one" ${syntax}="one">
741+
<template (one)="one">
690742
{{ one }}
691743
</template>
692-
<template slot="two" ${syntax}="two">
744+
<template (two)="two">
693745
{{ two }}
694746
</template>
695747
</foo>
@@ -699,97 +751,47 @@ describe('Component scoped slot', () => {
699751
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo default from foo one from foo two`)
700752
})
701753

702-
it('nested + named + default slots', () => {
754+
it('shorthand without scope variable', () => {
703755
const vm = new Vue({
704756
template: `
705757
<foo>
706-
<template slot="one" ${syntax}="one">
707-
<bar ${syntax}="bar">
708-
{{ one }} {{ bar }}
709-
</bar>
710-
</template>
711-
<template slot="two" ${syntax}="two">
712-
<baz ${syntax}="baz">
713-
{{ two }} {{ baz }}
714-
</baz>
715-
</template>
758+
<template (one)>one</template>
759+
<template (two)>two</template>
716760
</foo>
717761
`,
718-
components: { Foo, Bar, Baz }
762+
components: { Foo }
719763
}).$mount()
720-
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one from bar from foo two from baz`)
764+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`onetwo`)
721765
})
722766

723-
it('should warn slot-props usage on non-component elements', () => {
767+
it('shorthand named slots on root', () => {
724768
const vm = new Vue({
725-
template: `<div ${syntax}="foo"/>`
769+
template: `
770+
<foo (one)="one">
771+
{{ one }}
772+
</foo>
773+
`,
774+
components: { Foo }
726775
}).$mount()
727-
expect(`slot-props cannot be used on non-component elements`).toHaveBeenWarned()
776+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one`)
728777
})
729-
}
730-
731-
// run tests for both full syntax and shorthand
732-
runSuite('slot-props')
733-
runSuite('()')
734-
735-
it('shorthand named slots', () => {
736-
const vm = new Vue({
737-
template: `
738-
<foo ()="foo">
739-
{{ foo }}
740-
<template (one)="one">
741-
{{ one }}
742-
</template>
743-
<template (two)="two">
744-
{{ two }}
745-
</template>
746-
</foo>
747-
`,
748-
components: { Foo }
749-
}).$mount()
750-
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo default from foo one from foo two`)
751-
})
752778

753-
it('shorthand without scope variable', () => {
754-
const vm = new Vue({
755-
template: `
756-
<foo>
757-
<template (one)>one</template>
758-
<template (two)>two</template>
759-
</foo>
760-
`,
761-
components: { Foo }
762-
}).$mount()
763-
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`onetwo`)
764-
})
765-
766-
it('shorthand named slots on root', () => {
767-
const vm = new Vue({
768-
template: `
769-
<foo (one)="one">
770-
{{ one }}
771-
</foo>
772-
`,
773-
components: { Foo }
774-
}).$mount()
775-
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one`)
776-
})
777-
778-
it('dynamic shorthand', () => {
779-
const vm = new Vue({
780-
data: {
781-
a: 'one',
782-
b: 'two'
783-
},
784-
template: `
785-
<foo>
786-
<template :(a)="one">{{ one }} </template>
787-
<template :(b)="two">{{ two }}</template>
788-
</foo>
789-
`,
790-
components: { Foo }
791-
}).$mount()
792-
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one from foo two`)
779+
it('dynamic shorthand', () => {
780+
const vm = new Vue({
781+
data: {
782+
a: 'one',
783+
b: 'two'
784+
},
785+
template: `
786+
<foo>
787+
<template :(a)="one">{{ one }} </template>
788+
<template :(b)="two">{{ two }}</template>
789+
</foo>
790+
`,
791+
components: { Foo }
792+
}).$mount()
793+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one from foo two`)
794+
})
793795
})
794-
})
796+
}
795797
})

Diff for: test/unit/karma.base.config.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const alias = require('../../scripts/alias')
2+
const featureFlags = require('../../scripts/feature-flags')
23
const webpack = require('webpack')
34

45
const webpackConfig = {
@@ -20,7 +21,8 @@ const webpackConfig = {
2021
__WEEX__: false,
2122
'process.env': {
2223
TRANSITION_DURATION: process.env.CI ? 100 : 50,
23-
TRANSITION_BUFFER: 10
24+
TRANSITION_BUFFER: 10,
25+
...featureFlags
2426
}
2527
})
2628
],

0 commit comments

Comments
 (0)