From cea8b25fedae3e3aa4e67067de13188b3e7a448a Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 16 Nov 2020 11:35:30 -0500 Subject: [PATCH] wip: fix useCssVars helper call + tests --- .../__snapshots__/compileScript.spec.ts.snap | 124 +++++++++++------- .../__tests__/compileScript.spec.ts | 48 +++---- packages/compiler-sfc/src/compileScript.ts | 38 ++++-- packages/compiler-sfc/src/genCssVars.ts | 6 +- 4 files changed, 128 insertions(+), 88 deletions(-) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index a6db4207..baac4d58 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -2,9 +2,9 @@ exports[`SFC compile `) assertCode(content) - expect(content).toMatch(`export default defineComponent({ + expect(content).toMatch(`export default _defineComponent({ + expose: [], props: { foo: String }, emits: ['a', 'b'], setup(__props, { props, emit }) {`) @@ -410,14 +412,14 @@ const { props, emit } = defineOptions({ let c = () => {} let d `) - expect(content).toMatch(`import { ref } from 'vue'`) + expect(content).toMatch(`import { ref as _ref } from 'vue'`) expect(content).not.toMatch(`ref: foo`) expect(content).not.toMatch(`ref: a`) expect(content).not.toMatch(`ref: b`) - expect(content).toMatch(`const foo = ref()`) - expect(content).toMatch(`const a = ref(1)`) + expect(content).toMatch(`const foo = _ref()`) + expect(content).toMatch(`const a = _ref(1)`) expect(content).toMatch(` - const b = ref({ + const b = _ref({ count: 0 }) `) @@ -441,7 +443,7 @@ const { props, emit } = defineOptions({ } `) expect(content).toMatch(` - const a = ref(1), b = ref(2), c = ref({ + const a = _ref(1), b = _ref(2), c = _ref({ count: 0 }) `) @@ -526,15 +528,15 @@ const { props, emit } = defineOptions({ console.log(n, a, c, d, f, g) `) expect(content).toMatch( - `const n = ref(1), { a: __a, b: __c, d: __d = 1, e: __f = 2, ...__g } = useFoo()` + `const n = _ref(1), { a: __a, b: __c, d: __d = 1, e: __f = 2, ...__g } = useFoo()` ) - expect(content).toMatch(`\nconst a = ref(__a);`) - expect(content).not.toMatch(`\nconst b = ref(__b);`) - expect(content).toMatch(`\nconst c = ref(__c);`) - expect(content).toMatch(`\nconst d = ref(__d);`) - expect(content).not.toMatch(`\nconst e = ref(__e);`) - expect(content).toMatch(`\nconst f = ref(__f);`) - expect(content).toMatch(`\nconst g = ref(__g);`) + expect(content).toMatch(`\nconst a = _ref(__a);`) + expect(content).not.toMatch(`\nconst b = _ref(__b);`) + expect(content).toMatch(`\nconst c = _ref(__c);`) + expect(content).toMatch(`\nconst d = _ref(__d);`) + expect(content).not.toMatch(`\nconst e = _ref(__e);`) + expect(content).toMatch(`\nconst f = _ref(__f);`) + expect(content).toMatch(`\nconst g = _ref(__g);`) expect(content).toMatch( `console.log(n.value, a.value, c.value, d.value, f.value, g.value)` ) @@ -556,11 +558,11 @@ const { props, emit } = defineOptions({ console.log(n, a, b, c) `) expect(content).toMatch( - `const n = ref(1), [__a, __b = 1, ...__c] = useFoo()` + `const n = _ref(1), [__a, __b = 1, ...__c] = useFoo()` ) - expect(content).toMatch(`\nconst a = ref(__a);`) - expect(content).toMatch(`\nconst b = ref(__b);`) - expect(content).toMatch(`\nconst c = ref(__c);`) + expect(content).toMatch(`\nconst a = _ref(__a);`) + expect(content).toMatch(`\nconst b = _ref(__b);`) + expect(content).toMatch(`\nconst c = _ref(__c);`) expect(content).toMatch(`console.log(n.value, a.value, b.value, c.value)`) expect(content).toMatch(`return { n, a, b, c }`) expect(bindings).toStrictEqual({ @@ -580,11 +582,11 @@ const { props, emit } = defineOptions({ `) expect(content).toMatch(`const [{ a: { b: __b }}] = useFoo()`) expect(content).toMatch(`const { c: [__d, __e] } = useBar()`) - expect(content).not.toMatch(`\nconst a = ref(__a);`) - expect(content).not.toMatch(`\nconst c = ref(__c);`) - expect(content).toMatch(`\nconst b = ref(__b);`) - expect(content).toMatch(`\nconst d = ref(__d);`) - expect(content).toMatch(`\nconst e = ref(__e);`) + expect(content).not.toMatch(`\nconst a = _ref(__a);`) + expect(content).not.toMatch(`\nconst c = _ref(__c);`) + expect(content).toMatch(`\nconst b = _ref(__b);`) + expect(content).toMatch(`\nconst d = _ref(__d);`) + expect(content).toMatch(`\nconst e = _ref(__e);`) expect(content).toMatch(`return { b, d, e }`) expect(bindings).toStrictEqual({ b: 'setup', diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index 47420ca3..a049d205 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -24,7 +24,11 @@ import { } from '@babel/types' import { walk } from 'estree-walker' import { RawSourceMap } from 'source-map' -import { genCssVarsCode, injectCssVarsCalls } from './genCssVars' +import { + CSS_VARS_HELPER, + genCssVarsCode, + injectCssVarsCalls +} from './genCssVars' import { compileTemplate, SFCTemplateCompileOptions } from './compileTemplate' const DEFINE_OPTIONS = 'defineOptions' @@ -165,6 +169,11 @@ export function compileScript( const scriptStartOffset = script && script.loc.start.offset const scriptEndOffset = script && script.loc.end.offset + function helper(key: string): string { + helperImports.add(key) + return `_${key}` + } + function parse( input: string, options: ParserOptions, @@ -240,11 +249,10 @@ export function compileScript( function processRefExpression(exp: Expression, statement: LabeledStatement) { if (exp.type === 'AssignmentExpression') { - helperImports.add('ref') const { left, right } = exp if (left.type === 'Identifier') { registerRefBinding(left) - s.prependRight(right.start! + startOffset, `ref(`) + s.prependRight(right.start! + startOffset, `${helper('ref')}(`) s.appendLeft(right.end! + startOffset, ')') } else if (left.type === 'ObjectPattern') { // remove wrapping parens @@ -272,7 +280,7 @@ export function compileScript( exp.expressions.forEach(e => processRefExpression(e, statement)) } else if (exp.type === 'Identifier') { registerRefBinding(exp) - s.appendLeft(exp.end! + startOffset, ` = ref()`) + s.appendLeft(exp.end! + startOffset, ` = ${helper('ref')}()`) } else { error(`ref: statements can only contain assignment expressions.`, exp) } @@ -326,7 +334,7 @@ export function compileScript( // append binding declarations after the parent statement s.appendLeft( statement.end! + startOffset, - `\nconst ${nameId.name} = ref(__${nameId.name});` + `\nconst ${nameId.name} = ${helper('ref')}(__${nameId.name});` ) } } @@ -360,7 +368,7 @@ export function compileScript( // append binding declarations after the parent statement s.appendLeft( statement.end! + startOffset, - `\nconst ${nameId.name} = ref(__${nameId.name});` + `\nconst ${nameId.name} = ${helper('ref')}(__${nameId.name});` ) } } @@ -744,7 +752,7 @@ export function compileScript( // 8. inject `useCssVars` calls if (hasCssVars) { - helperImports.add(`useCssVars`) + helperImports.add(CSS_VARS_HELPER) for (const style of styles) { const vars = style.attrs.vars if (typeof vars === 'string') { @@ -829,7 +837,6 @@ export function compileScript( if (isTS) { // for TS, make sure the exported type is still valid type with // correct props information - helperImports.add(`defineComponent`) // we have to use object spread for types to be merged properly // user's TS setting should compile it down to proper targets const def = defaultExport ? `\n ...${defaultTempVar},` : `` @@ -838,7 +845,9 @@ export function compileScript( // this allows `import { setup } from '*.vue'` for testing purposes. s.prependLeft( startOffset, - `\nexport default defineComponent({${def}${runtimeOptions}\n ${ + `\nexport default ${helper( + `defineComponent` + )}({${def}${runtimeOptions}\n ${ hasAwait ? `async ` : `` }setup(${args}) {\n` ) @@ -865,11 +874,12 @@ export function compileScript( } // 12. finalize Vue helper imports - // TODO account for cases where user imports a helper with the same name - // from a non-vue source - const helpers = [...helperImports].filter(i => !userImports[i]) - if (helpers.length) { - s.prepend(`import { ${helpers.join(', ')} } from 'vue'\n`) + if (helperImports.size > 0) { + s.prepend( + `import { ${[...helperImports] + .map(h => `${h} as _${h}`) + .join(', ')} } from 'vue'\n` + ) } s.trim() diff --git a/packages/compiler-sfc/src/genCssVars.ts b/packages/compiler-sfc/src/genCssVars.ts index 3d926cf5..69d1457f 100644 --- a/packages/compiler-sfc/src/genCssVars.ts +++ b/packages/compiler-sfc/src/genCssVars.ts @@ -10,6 +10,8 @@ import { SFCDescriptor } from './parse' import { rewriteDefault } from './rewriteDefault' import { ParserPlugin } from '@babel/parser' +export const CSS_VARS_HELPER = `useCssVars` + export function genCssVarsCode( varsExp: string, scoped: boolean, @@ -38,7 +40,7 @@ export function genCssVarsCode( }) .join('') - return `__useCssVars__(_ctx => (${transformedString})${ + return `_${CSS_VARS_HELPER}(_ctx => (${transformedString})${ scoped ? `, true` : `` })` } @@ -65,7 +67,7 @@ export function injectCssVarsCalls( return ( script + - `\nimport { useCssVars as __useCssVars__ } from 'vue'\n` + + `\nimport { ${CSS_VARS_HELPER} as _${CSS_VARS_HELPER} } from 'vue'\n` + `const __injectCSSVars__ = () => {\n${calls}}\n` + `const __setup__ = __default__.setup\n` + `__default__.setup = __setup__\n` +