-import MagicString from 'magic-string'
import {
BindingTypes,
UNREF,
import { walk } from 'estree-walker'
import { RawSourceMap } from 'source-map-js'
import {
- CSS_VARS_HELPER,
- genCssVarsCode,
- genNormalScriptCssVarsCode
-} from './style/cssVars'
+ processNormalScript,
+ normalScriptDefaultVar
+} from './script/normalScript'
+import { CSS_VARS_HELPER, genCssVarsCode } from './style/cssVars'
import { compileTemplate, SFCTemplateCompileOptions } from './compileTemplate'
import { warnOnce } from './warn'
-import { rewriteDefaultAST } from './rewriteDefault'
import { shouldTransform, transformAST } from '@vue/reactivity-transform'
import { transformDestructuredProps } from './script/definePropsDestructure'
import { ScriptCompileContext } from './script/context'
sfc: SFCDescriptor,
options: SFCScriptCompileOptions
): SFCScriptBlock {
- let { script, scriptSetup, source, filename } = sfc
- // feature flags
- // TODO remove in 3.4
- const enableReactivityTransform = !!options.reactivityTransform
- const isProd = !!options.isProd
- const genSourceMap = options.sourceMap !== false
- const hoistStatic = options.hoistStatic !== false && !script
- let refBindings: string[] | undefined
-
if (!options.id) {
warnOnce(
`compileScript now requires passing the \`id\` option.\n` +
)
}
+ const ctx = new ScriptCompileContext(sfc, options)
+ const { script, scriptSetup, source, filename } = sfc
+ const hoistStatic = options.hoistStatic !== false && !script
const scopeId = options.id ? options.id.replace(/^data-v-/, '') : ''
- const cssVars = sfc.cssVars
const scriptLang = script && script.lang
const scriptSetupLang = scriptSetup && scriptSetup.lang
- const genDefaultAs = options.genDefaultAs
- ? `const ${options.genDefaultAs} =`
- : `export default`
- const normalScriptDefaultVar = `__default__`
- const ctx = new ScriptCompileContext(sfc, options)
- const { isTS } = ctx
+ // TODO remove in 3.4
+ const enableReactivityTransform = !!options.reactivityTransform
+ let refBindings: string[] | undefined
if (!scriptSetup) {
if (!script) {
throw new Error(`[@vue/compiler-sfc] SFC contains no <script> tags.`)
}
- if (scriptLang && !ctx.isJS && !ctx.isTS) {
- // do not process non js/ts script blocks
- return script
- }
// normal <script> only
- try {
- let content = script.content
- let map = script.map
- const scriptAst = ctx.scriptAst!
- const bindings = analyzeScriptBindings(scriptAst.body)
- if (enableReactivityTransform && shouldTransform(content)) {
- const s = new MagicString(source)
- const startOffset = script.loc.start.offset
- const endOffset = script.loc.end.offset
- const { importedHelpers } = transformAST(scriptAst, s, startOffset)
- if (importedHelpers.length) {
- s.prepend(
- `import { ${importedHelpers
- .map(h => `${h} as _${h}`)
- .join(', ')} } from 'vue'\n`
- )
- }
- s.remove(0, startOffset)
- s.remove(endOffset, source.length)
- content = s.toString()
- if (genSourceMap) {
- map = s.generateMap({
- source: filename,
- hires: true,
- includeContent: true
- }) as unknown as RawSourceMap
- }
- }
- if (cssVars.length || options.genDefaultAs) {
- const defaultVar = options.genDefaultAs || normalScriptDefaultVar
- const s = new MagicString(content)
- rewriteDefaultAST(ctx.scriptAst!.body, s, defaultVar)
- content = s.toString()
- if (cssVars.length) {
- content += genNormalScriptCssVarsCode(
- cssVars,
- bindings,
- scopeId,
- isProd,
- defaultVar
- )
- }
- if (!options.genDefaultAs) {
- content += `\nexport default ${defaultVar}`
- }
- }
- return {
- ...script,
- content,
- map,
- bindings,
- scriptAst: scriptAst.body
- }
- } catch (e: any) {
- // silently fallback if parse fails since user may be using custom
- // babel syntax
- return script
- }
+ return processNormalScript(ctx, scopeId)
}
if (script && scriptLang !== scriptSetupLang) {
let isUsedInTemplate = needTemplateUsageCheck
if (
needTemplateUsageCheck &&
- isTS &&
+ ctx.isTS &&
sfc.template &&
!sfc.template.src &&
!sfc.template.lang
)
}
- if (isTS) {
+ if (ctx.isTS) {
// move all Type declarations to outer scope
if (
node.type.startsWith('TS') ||
// 8. inject `useCssVars` calls
if (
- cssVars.length &&
+ sfc.cssVars.length &&
// no need to do this when targeting SSR
!(options.inlineTemplate && options.templateOptions?.ssr)
) {
ctx.helperImports.add('unref')
ctx.s.prependLeft(
startOffset,
- `\n${genCssVarsCode(cssVars, ctx.bindingMetadata, scopeId, isProd)}\n`
+ `\n${genCssVarsCode(
+ sfc.cssVars,
+ ctx.bindingMetadata,
+ scopeId,
+ !!options.isProd
+ )}\n`
)
}
}
// inject temp variables for async context preservation
if (hasAwait) {
- const any = isTS ? `: any` : ``
+ const any = ctx.isTS ? `: any` : ``
ctx.s.prependLeft(startOffset, `\nlet __temp${any}, __restore${any}\n`)
}
...(options.templateOptions &&
options.templateOptions.compilerOptions),
inline: true,
- isTS,
+ isTS: ctx.isTS,
bindingMetadata: ctx.bindingMetadata
}
})
}
// 11. finalize default export
+ const genDefaultAs = options.genDefaultAs
+ ? `const ${options.genDefaultAs} =`
+ : `export default`
+
let runtimeOptions = ``
if (!ctx.hasDefaultExportName && filename && filename !== DEFAULT_FILENAME) {
const match = filename.match(/([^/\\]+)\.\w+$/)
const exposeCall =
ctx.hasDefineExposeCall || options.inlineTemplate ? `` : ` __expose();\n`
// wrap setup code with function.
- if (isTS) {
+ if (ctx.isTS) {
// for TS, make sure the exported type is still valid type with
// correct props information
// we have to use object spread for types to be merged properly
bindings: ctx.bindingMetadata,
imports: userImports,
content: ctx.s.toString(),
- map: genSourceMap
- ? (ctx.s.generateMap({
- source: filename,
- hires: true,
- includeContent: true
- }) as unknown as RawSourceMap)
- : undefined,
+ map:
+ options.sourceMap !== false
+ ? (ctx.s.generateMap({
+ source: filename,
+ hires: true,
+ includeContent: true
+ }) as unknown as RawSourceMap)
+ : undefined,
scriptAst: scriptAst?.body,
scriptSetupAst: scriptSetupAst?.body
}
--- /dev/null
+import { shouldTransform, transformAST } from '@vue/reactivity-transform'
+import { analyzeScriptBindings } from './analyzeScriptBindings'
+import { ScriptCompileContext } from './context'
+import MagicString from 'magic-string'
+import { RawSourceMap } from 'source-map-js'
+import { rewriteDefaultAST } from '../rewriteDefault'
+import { genNormalScriptCssVarsCode } from '../style/cssVars'
+
+export const normalScriptDefaultVar = `__default__`
+
+export function processNormalScript(
+ ctx: ScriptCompileContext,
+ scopeId: string
+) {
+ const script = ctx.descriptor.script!
+ if (script.lang && !ctx.isJS && !ctx.isTS) {
+ // do not process non js/ts script blocks
+ return script
+ }
+ try {
+ let content = script.content
+ let map = script.map
+ const scriptAst = ctx.scriptAst!
+ const bindings = analyzeScriptBindings(scriptAst.body)
+ const { source, filename, cssVars } = ctx.descriptor
+ const { sourceMap, genDefaultAs, isProd } = ctx.options
+
+ // TODO remove in 3.4
+ if (ctx.options.reactivityTransform && shouldTransform(content)) {
+ const s = new MagicString(source)
+ const startOffset = script.loc.start.offset
+ const endOffset = script.loc.end.offset
+ const { importedHelpers } = transformAST(scriptAst, s, startOffset)
+ if (importedHelpers.length) {
+ s.prepend(
+ `import { ${importedHelpers
+ .map(h => `${h} as _${h}`)
+ .join(', ')} } from 'vue'\n`
+ )
+ }
+ s.remove(0, startOffset)
+ s.remove(endOffset, source.length)
+ content = s.toString()
+ if (sourceMap !== false) {
+ map = s.generateMap({
+ source: filename,
+ hires: true,
+ includeContent: true
+ }) as unknown as RawSourceMap
+ }
+ }
+
+ if (cssVars.length || genDefaultAs) {
+ const defaultVar = genDefaultAs || normalScriptDefaultVar
+ const s = new MagicString(content)
+ rewriteDefaultAST(scriptAst.body, s, defaultVar)
+ content = s.toString()
+ if (cssVars.length) {
+ content += genNormalScriptCssVarsCode(
+ cssVars,
+ bindings,
+ scopeId,
+ !!isProd,
+ defaultVar
+ )
+ }
+ if (!genDefaultAs) {
+ content += `\nexport default ${defaultVar}`
+ }
+ }
+ return {
+ ...script,
+ content,
+ map,
+ bindings,
+ scriptAst: scriptAst.body
+ }
+ } catch (e: any) {
+ // silently fallback if parse fails since user may be using custom
+ // babel syntax
+ return script
+ }
+}