{
+ let a = '' + lett
+ v = a
+ }"/>
+
{
+ // nested scopes
+ (()=>{
+ let x = a
+ (()=>{
+ let z = x
+ let z2 = z
+ })
+ let lz = z
+ })
+ v = a
+ }"/>
+
+ `,
+ { inlineTemplate: true }
+ )
+ // known const ref: set value
+ expect(content).toMatch(`count.value = 1`)
+ // const but maybe ref: only assign after check
+ expect(content).toMatch(`maybe.value = count.value`)
+ // let: handle both cases
+ expect(content).toMatch(
+ `isRef(lett) ? lett.value = count.value : lett = count.value`
+ )
+ expect(content).toMatch(`isRef(v) ? v.value += 1 : v += 1`)
+ expect(content).toMatch(`isRef(v) ? v.value -= 1 : v -= 1`)
+ expect(content).toMatch(`isRef(v) ? v.value = a : v = a`)
+ expect(content).toMatch(`isRef(v) ? v.value = _ctx.a : v = _ctx.a`)
+ assertCode(content)
+ })
+
+ test('template update expression codegen', () => {
+ const { content } = compile(
+ `
+
+
+
+
+
+
+
+
+ `,
+ { inlineTemplate: true }
+ )
+ // known const ref: set value
+ expect(content).toMatch(`count.value++`)
+ expect(content).toMatch(`--count.value`)
+ // const but maybe ref (non-ref case ignored)
+ expect(content).toMatch(`maybe.value++`)
+ expect(content).toMatch(`--maybe.value`)
+ // let: handle both cases
+ expect(content).toMatch(`isRef(lett) ? lett.value++ : lett++`)
+ expect(content).toMatch(`isRef(lett) ? --lett.value : --lett`)
+ assertCode(content)
+ })
+
+ test('template destructure assignment codegen', () => {
+ const { content } = compile(
+ `
+
+
+
+
+
+ `,
+ { inlineTemplate: true }
+ )
+ // known const ref: set value
+ expect(content).toMatch(`({ count: count.value } = val)`)
+ // const but maybe ref (non-ref case ignored)
+ expect(content).toMatch(`[maybe.value] = val`)
+ // let: assumes non-ref
+ expect(content).toMatch(`{ lett: lett } = val`)
+ assertCode(content)
+ })
+
+ // test('ssr codegen', () => {
+ // const { content } = compile(
+ // `
+ //
+ //
+ // {{ count }}
+ // static
+ //
+ //
+ // `,
+ // {
+ // inlineTemplate: true,
+ // templateOptions: {
+ // ssr: true,
+ // },
+ // }
+ // )
+ // expect(content).toMatch(`\n __ssrInlineRender: true,\n`)
+ // expect(content).toMatch(`return (_ctx, _push`)
+ // expect(content).toMatch(`ssrInterpolate`)
+ // expect(content).not.toMatch(`useCssVars`)
+ // expect(content).toMatch(`"--${mockId}-count": (count.value)`)
+ // expect(content).toMatch(`"--${mockId}-style\\\\.color": (style.color)`)
+ // assertCode(content)
+ // })
+
+ test('the v-for wrapped in parentheses can be correctly parsed & inline is false', () => {
+ expect(() =>
+ compile(
+ `
+
+
+
+
+ `,
+ {
+ inlineTemplate: false,
+ }
+ )
+ ).not.toThrowError()
+ })
+ })
+
+ describe('with TypeScript', () => {
+ test('hoist type declarations', () => {
+ const { content } = compile(`
+ `)
+ assertCode(content)
+ })
+
+ test('runtime Enum', () => {
+ const { content, bindings } = compile(
+ ``
+ )
+ assertCode(content)
+ expect(bindings).toStrictEqual({
+ Foo: BindingTypes.LITERAL_CONST,
+ })
+ })
+
+ test('runtime Enum in normal script', () => {
+ const { content, bindings } = compile(
+ `
+ `
+ )
+ assertCode(content)
+ expect(bindings).toStrictEqual({
+ D: BindingTypes.LITERAL_CONST,
+ C: BindingTypes.LITERAL_CONST,
+ B: BindingTypes.LITERAL_CONST,
+ Foo: BindingTypes.LITERAL_CONST,
+ })
+ })
+
+ test('const Enum', () => {
+ const { content, bindings } = compile(
+ ``,
+ { hoistStatic: true }
+ )
+ assertCode(content)
+ expect(bindings).toStrictEqual({
+ Foo: BindingTypes.LITERAL_CONST,
+ })
+ })
+
+ // test('import type', () => {
+ // const { content } = compile(
+ // ``
+ // )
+ // expect(content).toMatch(`return { get Baz() { return Baz } }`)
+ // assertCode(content)
+ // })
+ })
+
+ // describe('async/await detection', () => {
+ // function assertAwaitDetection(code: string, shouldAsync = true) {
+ // const { content } = compile(``, {
+ // reactivityTransform: true,
+ // })
+ // if (shouldAsync) {
+ // expect(content).toMatch(`let __temp, __restore`)
+ // }
+ // expect(content).toMatch(`${shouldAsync ? `async ` : ``}setup(`)
+ // assertCode(content)
+ // return content
+ // }
+
+ // test('expression statement', () => {
+ // assertAwaitDetection(`await foo`)
+ // })
+
+ // test('variable', () => {
+ // assertAwaitDetection(`const a = 1 + (await foo)`)
+ // })
+
+ // test('ref', () => {
+ // assertAwaitDetection(`let a = $ref(1 + (await foo))`)
+ // })
+
+ // // #4448
+ // test('nested await', () => {
+ // assertAwaitDetection(`await (await foo)`)
+ // assertAwaitDetection(`await ((await foo))`)
+ // assertAwaitDetection(`await (await (await foo))`)
+ // })
+
+ // // should prepend semicolon
+ // test('nested leading await in expression statement', () => {
+ // const code = assertAwaitDetection(`foo()\nawait 1 + await 2`)
+ // expect(code).toMatch(`foo()\n;(`)
+ // })
+
+ // // #4596 should NOT prepend semicolon
+ // test('single line conditions', () => {
+ // const code = assertAwaitDetection(`if (false) await foo()`)
+ // expect(code).not.toMatch(`if (false) ;(`)
+ // })
+
+ // test('nested statements', () => {
+ // assertAwaitDetection(`if (ok) { await foo } else { await bar }`)
+ // })
+
+ // test('multiple `if` nested statements', () => {
+ // assertAwaitDetection(`if (ok) {
+ // let a = 'foo'
+ // await 0 + await 1
+ // await 2
+ // } else if (a) {
+ // await 10
+ // if (b) {
+ // await 0 + await 1
+ // } else {
+ // let a = 'foo'
+ // await 2
+ // }
+ // if (b) {
+ // await 3
+ // await 4
+ // }
+ // } else {
+ // await 5
+ // }`)
+ // })
+
+ // test('multiple `if while` nested statements', () => {
+ // assertAwaitDetection(`if (ok) {
+ // while (d) {
+ // await 5
+ // }
+ // while (d) {
+ // await 5
+ // await 6
+ // if (c) {
+ // let f = 10
+ // 10 + await 7
+ // } else {
+ // await 8
+ // await 9
+ // }
+ // }
+ // }`)
+ // })
+
+ // test('multiple `if for` nested statements', () => {
+ // assertAwaitDetection(`if (ok) {
+ // for (let a of [1,2,3]) {
+ // await a
+ // }
+ // for (let a of [1,2,3]) {
+ // await a
+ // await a
+ // }
+ // }`)
+ // })
+
+ // test('should ignore await inside functions', () => {
+ // // function declaration
+ // assertAwaitDetection(`async function foo() { await bar }`, false)
+ // // function expression
+ // assertAwaitDetection(`const foo = async () => { await bar }`, false)
+ // // object method
+ // assertAwaitDetection(`const obj = { async method() { await bar }}`, false)
+ // // class method
+ // assertAwaitDetection(
+ // `const cls = class Foo { async method() { await bar }}`,
+ // false
+ // )
+ // })
+ // })
+
+ describe('errors', () => {
+ // test('`)
+ // ).toThrow(``)
+ ).toThrow(moduleErrorMsg)
+
+ expect(() =>
+ compile(``)
+ ).toThrow(moduleErrorMsg)
+
+ expect(() =>
+ compile(``)
+ ).toThrow(moduleErrorMsg)
+ })
+
+ test('defineProps/Emit() referencing local var', () => {
+ expect(() =>
+ compile(``)
+ ).toThrow(`cannot reference locally declared variables`)
+
+ expect(() =>
+ compile(``)
+ ).toThrow(`cannot reference locally declared variables`)
+
+ // #4644
+ expect(() =>
+ compile(`
+
+ `)
+ ).not.toThrow(`cannot reference locally declared variables`)
+ })
+
+ test('should allow defineProps/Emit() referencing scope var', () => {
+ assertCode(
+ compile(``).content
+ )
+ })
+
+ test('should allow defineProps/Emit() referencing imported binding', () => {
+ assertCode(
+ compile(``).content
+ )
+ })
+ })
+})
+
+describe('SFC analyze
+ `)
+
+ expect(scriptAst).toBeDefined()
+ })
+
+ it('recognizes props array declaration', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.PROPS,
+ bar: BindingTypes.PROPS,
+ })
+ expect(bindings!.__isScriptSetup).toBe(false)
+ })
+
+ it('recognizes props object declaration', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.PROPS,
+ bar: BindingTypes.PROPS,
+ baz: BindingTypes.PROPS,
+ qux: BindingTypes.PROPS,
+ })
+ expect(bindings!.__isScriptSetup).toBe(false)
+ })
+
+ it('recognizes setup return', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.SETUP_MAYBE_REF,
+ bar: BindingTypes.SETUP_MAYBE_REF,
+ })
+ expect(bindings!.__isScriptSetup).toBe(false)
+ })
+
+ it('recognizes exported vars', () => {
+ const { bindings } = compile(`
+
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.LITERAL_CONST,
+ })
+ })
+
+ it('recognizes async setup return', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.SETUP_MAYBE_REF,
+ bar: BindingTypes.SETUP_MAYBE_REF,
+ })
+ expect(bindings!.__isScriptSetup).toBe(false)
+ })
+
+ it('recognizes data return', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.DATA,
+ bar: BindingTypes.DATA,
+ })
+ })
+
+ it('recognizes methods', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({ foo: BindingTypes.OPTIONS })
+ })
+
+ it('recognizes computeds', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.OPTIONS,
+ bar: BindingTypes.OPTIONS,
+ })
+ })
+
+ it('recognizes injections array declaration', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.OPTIONS,
+ bar: BindingTypes.OPTIONS,
+ })
+ })
+
+ it('recognizes injections object declaration', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.OPTIONS,
+ bar: BindingTypes.OPTIONS,
+ })
+ })
+
+ it('works for mixed bindings', () => {
+ const { bindings } = compile(`
+
+ `)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.OPTIONS,
+ bar: BindingTypes.PROPS,
+ baz: BindingTypes.SETUP_MAYBE_REF,
+ qux: BindingTypes.DATA,
+ quux: BindingTypes.OPTIONS,
+ quuz: BindingTypes.OPTIONS,
+ })
+ })
+
+ it('works for script setup', () => {
+ const { bindings } = compile(`
+
+ `)
+
+ expect(bindings).toStrictEqual({
+ r: BindingTypes.SETUP_CONST,
+ a: BindingTypes.SETUP_REF,
+ b: BindingTypes.SETUP_LET,
+ c: BindingTypes.LITERAL_CONST,
+ d: BindingTypes.SETUP_MAYBE_REF,
+ e: BindingTypes.SETUP_LET,
+ foo: BindingTypes.PROPS,
+ })
+ })
+
+ describe('auto name inference', () => {
+ test('basic', () => {
+ const { content } = compile(
+ `
+
{{ a }}`,
+ undefined,
+ {
+ filename: 'FooBar.vue',
+ }
+ )
+ expect(content).toMatch(`export default {
+ __name: 'FooBar'`)
+ assertCode(content)
+ })
+
+ test('do not overwrite manual name (object)', () => {
+ const { content } = compile(
+ `
+
+
{{ a }}`,
+ undefined,
+ {
+ filename: 'FooBar.vue',
+ }
+ )
+ expect(content).not.toMatch(`name: 'FooBar'`)
+ expect(content).toMatch(`name: 'Baz'`)
+ assertCode(content)
+ })
+
+ test('do not overwrite manual name (call)', () => {
+ const { content } = compile(
+ `
+
+
{{ a }}`,
+ undefined,
+ {
+ filename: 'FooBar.vue',
+ }
+ )
+ expect(content).not.toMatch(`name: 'FooBar'`)
+ expect(content).toMatch(`name: 'Baz'`)
+ assertCode(content)
+ })
+ })
+})
+
+// describe('SFC genDefaultAs', () => {
+// test('normal `,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).toMatch(`const _sfc_ = {}`)
+// assertCode(content)
+// })
+
+// test('normal
+// `,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).not.toMatch('__default__')
+// expect(content).toMatch(`const _sfc_ = {}`)
+// assertCode(content)
+// })
+
+// test('
+// `,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).toMatch(
+// `const _sfc_ = /*#__PURE__*/Object.assign(__default__`
+// )
+// assertCode(content)
+// })
+
+// test('
+// `,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).toMatch(
+// `const _sfc_ = /*#__PURE__*/Object.assign(__default__`
+// )
+// assertCode(content)
+// })
+
+// test('`,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).toMatch(`const _sfc_ = {\n setup`)
+// assertCode(content)
+// })
+
+// test('`,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).toMatch(`const _sfc_ = /*#__PURE__*/_defineComponent(`)
+// assertCode(content)
+// })
+
+// test('
+// `,
+// {
+// genDefaultAs: '_sfc_',
+// }
+// )
+// expect(content).not.toMatch('export default')
+// expect(content).toMatch(
+// `const _sfc_ = /*#__PURE__*/_defineComponent({\n ...__default__`
+// )
+// assertCode(content)
+// })
+
+// test('binding type for edge cases', () => {
+// const { bindings } = compile(
+// ``
+// )
+// expect(bindings).toStrictEqual({
+// toRef: BindingTypes.SETUP_CONST,
+// props: BindingTypes.SETUP_REACTIVE_CONST,
+// foo: BindingTypes.SETUP_REF,
+// })
+// })
+// })
diff --git a/packages/uni-app-uts/__tests__/android/sfc/utils.ts b/packages/uni-app-uts/__tests__/android/sfc/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0a0be40c8224d4ef3475982d847b7334969ad2d5
--- /dev/null
+++ b/packages/uni-app-uts/__tests__/android/sfc/utils.ts
@@ -0,0 +1,58 @@
+import { parse, SFCParseOptions } from '@vue/compiler-sfc'
+import { parse as babelParse } from '@babel/parser'
+
+import {
+ compileScript,
+ SFCScriptCompileOptions,
+} from '../../../src/plugins/android/uvue/sfc/compiler/compileScript'
+import { genTemplateCode } from '../../../src/plugins/android/uvue/code/template'
+import { resolveGenTemplateCodeOptions } from '../../../src/plugins/android/uvue/sfc/template'
+export const mockId = 'xxxxxxxx'
+
+export function compileSFCScript(
+ src: string,
+ options?: Partial
,
+ parseOptions?: SFCParseOptions
+) {
+ const { descriptor } = parse(src, parseOptions)
+ const result = compileScript(descriptor, {
+ ...options,
+ id: mockId,
+ className: '',
+ inlineTemplate: true,
+ scriptAndScriptSetup: true,
+ })
+ if (options?.inlineTemplate) {
+ const isInline = !!descriptor.scriptSetup
+ const templateResult = genTemplateCode(
+ descriptor,
+ resolveGenTemplateCodeOptions(descriptor.filename, src, descriptor, {
+ mode: 'module',
+ inline: isInline,
+ rootDir: '',
+ sourceMap: false,
+ bindingMetadata: result.bindings,
+ })
+ )
+ result.content = result.content.replace(
+ `"INLINE_RENDER"`,
+ templateResult.code
+ )
+ }
+ return result
+}
+
+export function assertCode(code: string) {
+ // parse the generated code to make sure it is valid
+ try {
+ babelParse(code, {
+ sourceType: 'module',
+ plugins: ['typescript'],
+ })
+ } catch (e: any) {
+ console.log(code, e)
+ throw e
+ }
+ // console.log(code)
+ expect(code).toMatchSnapshot()
+}
diff --git a/packages/uni-app-uts/__tests__/android/transforms/__snapshots__/transformExpressions.spec.ts.snap b/packages/uni-app-uts/__tests__/android/transforms/__snapshots__/transformExpressions.spec.ts.snap
index 9309115b58b6ed19d7726ef77e9e285a1d013176..59726634ef7692ea447a2a1bc295474a4cc0ac70 100644
--- a/packages/uni-app-uts/__tests__/android/transforms/__snapshots__/transformExpressions.spec.ts.snap
+++ b/packages/uni-app-uts/__tests__/android/transforms/__snapshots__/transformExpressions.spec.ts.snap
@@ -1,8 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`compiler: expression transform bindingMetadata inline mode 1`] = `"createElementVNode("view", null, toDisplayString(__props.props) + " " + toDisplayString(unref(setup)) + " " + toDisplayString(setupConst) + " " + toDisplayString(_ctx.data) + " " + toDisplayString(_ctx.options) + " " + toDisplayString(isNaN), 1 /* TEXT */)"`;
+exports[`compiler: expression transform bindingMetadata inline mode 1`] = `"createElementVNode("view", null, toDisplayString(__props.props) + " " + toDisplayString(unref(setup)) + " " + toDisplayString(setupConst) + " " + toDisplayString(_ctx.data) + " " + toDisplayString(_ctx.options) + " " + toDisplayString(isNaN.value), 1 /* TEXT */)"`;
-exports[`compiler: expression transform bindingMetadata non-inline mode 1`] = `"createElementVNode("view", null, toDisplayString($props.props) + " " + toDisplayString($setup.setup) + " " + toDisplayString($data.data) + " " + toDisplayString($options.options) + " " + toDisplayString(isNaN), 1 /* TEXT */)"`;
+exports[`compiler: expression transform bindingMetadata non-inline mode 1`] = `"createElementVNode("view", null, toDisplayString($props.props) + " " + toDisplayString($setup.setup) + " " + toDisplayString($data.data) + " " + toDisplayString($options.options) + " " + toDisplayString($setup.isNaN), 1 /* TEXT */)"`;
exports[`compiler: expression transform bindingMetadata should not prefix temp variable of for loop 1`] = `
"createVNode(_component_div, utsMapOf({
diff --git a/packages/uni-app-uts/__tests__/android/transforms/transformExpressions.spec.ts b/packages/uni-app-uts/__tests__/android/transforms/transformExpressions.spec.ts
index 1432dec1ea1ab6e7d02dd00a35f94acd91bc8a24..1ffd78aee1760c414f6efbefa063b2ec858a5712 100644
--- a/packages/uni-app-uts/__tests__/android/transforms/transformExpressions.spec.ts
+++ b/packages/uni-app-uts/__tests__/android/transforms/transformExpressions.spec.ts
@@ -532,7 +532,7 @@ describe('compiler: expression transform', () => {
)
expect(code).toMatch(`$props.props`)
expect(code).toMatch(`$setup.setup`)
- // expect(code).toMatch(`$setup.isNaN`)
+ expect(code).toMatch(`$setup.isNaN`)
expect(code).toMatch(`$data.data`)
expect(code).toMatch(`$options.options`)
// expect(code).toMatch(`_ctx, _cache, $props, $setup, $data, $options`)
@@ -585,8 +585,7 @@ describe('compiler: expression transform', () => {
expect(code).toMatch(`toDisplayString(setupConst)`)
expect(code).toMatch(`_ctx.data`)
expect(code).toMatch(`_ctx.options`)
- // isNaN 设置了全局方法
- // expect(code).toMatch(`isNaN.value`)
+ expect(code).toMatch(`isNaN.value`)
expect(code).toMatchSnapshot()
})
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/compiler/codegen.ts b/packages/uni-app-uts/src/plugins/android/uvue/compiler/codegen.ts
index 4f9697e5550d67abd37ba400721334d0d67f88e5..712346bd42a385ba9bb7b2734ab29961b05ba7a9 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/compiler/codegen.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/compiler/codegen.ts
@@ -99,7 +99,7 @@ function createCodegenContext(
rootDir = '',
targetLanguage = 'kotlin',
mode = 'default',
- prefixIdentifiers = false,
+ prefixIdentifiers = mode === 'module',
bindingMetadata = {},
inline = false,
sourceMap = false,
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/compiler/index.ts b/packages/uni-app-uts/src/plugins/android/uvue/compiler/index.ts
index 7d13fb290a6cdd5edc3d2b0bccf690f2ab260ebd..8703618dcabec4131984f6d8f1f4b9eb57de3b91 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/compiler/index.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/compiler/index.ts
@@ -107,7 +107,6 @@ export function compile(
transform(
ast,
extend({}, options, {
- prefixIdentifiers: options.prefixIdentifiers,
nodeTransforms: [
...nodeTransforms,
...getBaseNodeTransforms('/'),
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/compiler/options.ts b/packages/uni-app-uts/src/plugins/android/uvue/compiler/options.ts
index 565e718270e6e15608ef4a97d1702f067ead512c..327f3d22cd98223eea1ed5060cfcc662369a23ac 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/compiler/options.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/compiler/options.ts
@@ -3,6 +3,10 @@ import type { RawSourceMap } from 'source-map-js'
import { DirectiveTransform, NodeTransform } from './transform'
interface SharedTransformCodegenOptions {
+ /**
+ * @default 'default'
+ */
+ mode?: 'default' | 'module'
rootDir?: string
targetLanguage?: 'kotlin' | 'swift'
/**
@@ -32,11 +36,6 @@ interface SharedTransformCodegenOptions {
className?: string
}
export interface CodegenOptions extends SharedTransformCodegenOptions {
- /**
- * @default 'default'
- */
- mode?: 'default' | 'module'
-
inMap?: RawSourceMap
/**
* Generate source map?
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/compiler/transform.ts b/packages/uni-app-uts/src/plugins/android/uvue/compiler/transform.ts
index f0e443c1beecd23215e98b53fff4b7a260cded6e..30b7801bd4de1cd5c8d9589c11e7b6d0d4ea96a0 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/compiler/transform.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/compiler/transform.ts
@@ -116,11 +116,12 @@ export interface TransformContext
export function createTransformContext(
root: RootNode,
{
+ mode = 'default',
rootDir = '',
targetLanguage = 'kotlin',
filename = '',
cacheHandlers = false,
- prefixIdentifiers = false,
+ prefixIdentifiers = mode === 'module',
nodeTransforms = [],
directiveTransforms = {},
scopeId = null,
@@ -136,6 +137,7 @@ export function createTransformContext(
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
const context: TransformContext = {
// options
+ mode,
rootDir,
targetLanguage,
selfName: nameMatch && capitalize(camelize(nameMatch[1])),
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/compiler/transforms/transformExpression.ts b/packages/uni-app-uts/src/plugins/android/uvue/compiler/transforms/transformExpression.ts
index 414655de73b1742a39798e8f387048132a98606a..a6f130919f8efcacba75d76cc7c47229c2d5f975 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/compiler/transforms/transformExpression.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/compiler/transforms/transformExpression.ts
@@ -221,7 +221,12 @@ export function processExpression(
const isScopeVarReference = context.identifiers[rawExp]
const isAllowedGlobal = isGloballyWhitelisted(rawExp)
const isLiteral = isLiteralWhitelisted(rawExp)
- if (!asParams && !isScopeVarReference && !isAllowedGlobal && !isLiteral) {
+ if (
+ !asParams &&
+ !isScopeVarReference &&
+ !isLiteral &&
+ (!isAllowedGlobal || bindingMetadata[rawExp])
+ ) {
// const bindings exposed from setup can be skipped for patching but
// cannot be hoisted to module scope
if (bindingMetadata[node.content] === BindingTypes.SETUP_CONST) {
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/index.ts b/packages/uni-app-uts/src/plugins/android/uvue/index.ts
index f9dd685f0908c0d42afa4aac69ef82c5582d4db4..e4c402cc02d86d3b10ef3ea9013d0fc34bdbaa23 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/index.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/index.ts
@@ -258,7 +258,6 @@ export async function transformVue(
mode: 'module',
filename: relativeFileName,
className: className,
- prefixIdentifiers: true,
// 方便测试,build模式也提供sourceMap
// sourceMap: false,
sourceMap: needSourceMap,
diff --git a/packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/compileScript.ts b/packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/compileScript.ts
index 4fe7f36d48f7b8db859f64451bb7551a84db6b47..5b29c7025d220ca9ba748aa7ddebad1cb9adebff 100644
--- a/packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/compileScript.ts
+++ b/packages/uni-app-uts/src/plugins/android/uvue/sfc/compiler/compileScript.ts
@@ -13,6 +13,7 @@ import {
Identifier,
Statement,
CallExpression,
+ ExportSpecifier,
} from '@babel/types'
import { walk } from 'estree-walker'
import type { RawSourceMap } from 'source-map-js'
@@ -43,12 +44,22 @@ import {
} from './script/utils'
import { analyzeScriptBindings } from './script/analyzeScriptBindings'
import { parseUTSRelativeFilename } from '../../../utils'
-import { rewriteConsole } from './script/rewriteConsole'
+import { hasConsole, rewriteConsole } from './script/rewriteConsole'
import { hasDebugError, rewriteDebugError } from './script/rewriteDebugError'
+import { TypeScope } from './script/resolveType'
+
+export const normalScriptDefaultVar = `__default__`
export const DEFAULT_FILENAME = 'anonymous.vue'
export interface SFCScriptCompileOptions {
+ /**
+ * 是否同时支持使用