提交 55d07347 编写于 作者: fxy060608's avatar fxy060608

wip(uts): compiler

上级 43e7af69
......@@ -5,7 +5,6 @@ import {
resolveUtsAppModule,
resolveUTSCompiler,
} from '@dcloudio/uni-cli-shared'
import { isArray } from '@vue/shared'
const UTSProxyRE = /\?uts-proxy$/
......@@ -13,7 +12,6 @@ function isUTSProxy(id: string) {
return UTSProxyRE.test(id)
}
export function uniUtsV1Plugin(): Plugin {
let isFirst = true
return {
name: 'uni:uts-v1',
apply: 'build',
......@@ -33,7 +31,7 @@ export function uniUtsV1Plugin(): Plugin {
return ''
}
},
async transform(code, id, opts) {
async transform(_, id, opts) {
if (opts && opts.ssr) {
return
}
......@@ -41,86 +39,13 @@ export function uniUtsV1Plugin(): Plugin {
return
}
const { filename: module } = parseVueRequest(id.replace('\0', ''))
const {
getCompiler,
genProxyCode,
resolvePackage,
resolvePlatformIndex,
resolveRootIndex,
} = resolveUTSCompiler()
const pkg = resolvePackage(module)
if (!pkg) {
return
const result = await resolveUTSCompiler().compile(module)
if (result) {
result.deps.forEach((dep) => {
this.addWatchFile(dep)
})
return result.code
}
code = await genProxyCode(module, pkg)
if (process.env.NODE_ENV !== 'development') {
// 生产模式 支持同时生成 android 和 ios 的 uts 插件
if (
process.env.UNI_UTS_PLATFORM === 'app-android' ||
process.env.UNI_UTS_PLATFORM === 'app'
) {
const filename =
resolvePlatformIndex('app-android', module, pkg) ||
resolveRootIndex(module, pkg)
if (filename) {
await getCompiler('kotlin').runProd(filename)
}
}
if (
process.env.UNI_UTS_PLATFORM === 'app-ios' ||
process.env.UNI_UTS_PLATFORM === 'app'
) {
const filename =
resolvePlatformIndex('app-ios', module, pkg) ||
resolveRootIndex(module, pkg)
if (filename) {
await getCompiler('swift').runProd(filename)
}
}
} else {
// dev 模式仅 android 支持
if (process.env.UNI_UTS_PLATFORM === 'app-android') {
const filename =
resolvePlatformIndex('app-android', module, pkg) ||
resolveRootIndex(module, pkg)
if (filename) {
this.addWatchFile(filename)
const res = await getCompiler('kotlin').runDev(filename)
if (res) {
if (isArray(res.deps) && res.deps.length) {
// 添加其他文件的依赖
res.deps.forEach((dep) => {
this.addWatchFile(dep)
})
}
if (!isFirst) {
const files: string[] = []
if (process.env.UNI_APP_CHANGED_DEX_FILES) {
try {
files.push(
...JSON.parse(process.env.UNI_APP_CHANGED_DEX_FILES)
)
} catch (e) {}
}
if (res.dex) {
files.push(res.dex)
}
process.env.UNI_APP_CHANGED_DEX_FILES = JSON.stringify([
...new Set(files),
])
}
}
}
} else if (process.env.UNI_UTS_PLATFORM === 'app-ios') {
process.env.UNI_APP_IOS_UTS = 'true'
}
}
return code
},
buildEnd() {
isFirst = false
},
}
}
......@@ -19,7 +19,10 @@ export const isInHBuilderX = once(() => {
})
export const runByHBuilderX = once(() => {
return !!process.env.UNI_HBUILDERX_PLUGINS && !!process.env.RUN_BY_HBUILDERX
return (
!!process.env.UNI_HBUILDERX_PLUGINS &&
(!!process.env.RUN_BY_HBUILDERX || !!process.env.HX_Version)
)
})
/**
......
......@@ -5,6 +5,7 @@ export * from './env'
export * from './hbx'
export * from './ssr'
export * from './vue'
export * from './uts'
export * from './logs'
export * from './i18n'
export * from './deps'
......
......@@ -4,7 +4,6 @@ import path from 'path'
import debug from 'debug'
import resolve from 'resolve'
import { once } from '@dcloudio/uni-shared'
import * as UTSCompiler from '@dcloudio/uni-uts-v1'
import { normalizePath } from './utils'
import { isInHBuilderX } from './hbx/env'
......@@ -120,104 +119,3 @@ export function resolveComponentsLibPath() {
}
return componentsLibPath
}
/**
* 解析 app 平台的 uts 插件,任意平台(android|ios)存在即可
* @param id
* @param importer
* @returns
*/
export function resolveUtsAppModule(id: string, importer: string) {
id = path.resolve(importer, id)
if (id.includes('utssdk') || id.includes('uni_modules')) {
const parts = normalizePath(id).split('/')
const parentDir = parts[parts.length - 2]
if (parentDir === 'uni_modules' || parentDir === 'utssdk') {
const basedir = parentDir === 'uni_modules' ? 'utssdk' : ''
if (fs.existsSync(path.resolve(id, basedir, 'index.uts'))) {
return id
}
const resolvePlatformDir = (p: typeof process.env.UNI_UTS_PLATFORM) => {
return path.resolve(id, basedir, p)
}
const extname = ['.uts']
if (resolveUtsFile(resolvePlatformDir('app-android'), extname)) {
return id
}
if (resolveUtsFile(resolvePlatformDir('app-ios'), extname)) {
return id
}
}
}
}
export function resolveUtsModuleProxyFile(id: string, importer: string) {
const file = resolveUtsAppModule(id, importer)
if (file) {
return '\0' + file + '?uts-proxy'
}
}
// 仅限 root/uni_modules/test-plugin | root/utssdk/test-plugin 格式
export function resolveUtsModule(
id: string,
importer: string,
platform: typeof process.env.UNI_UTS_PLATFORM
) {
if (process.env.UNI_PLATFORM === 'app') {
return resolveUtsAppModule(id, importer)
}
id = path.resolve(importer, id)
if (id.includes('utssdk') || id.includes('uni_modules')) {
const parts = normalizePath(id).split('/')
const parentDir = parts[parts.length - 2]
if (parentDir === 'uni_modules' || parentDir === 'utssdk') {
const basedir = parentDir === 'uni_modules' ? 'utssdk' : ''
const resolvePlatformDir = (p: typeof process.env.UNI_UTS_PLATFORM) => {
return path.resolve(id, basedir, p)
}
let index = resolveUtsFile(resolvePlatformDir(platform))
if (index) {
return index
}
index = path.resolve(id, basedir, 'index.uts')
if (fs.existsSync(index)) {
return index
}
}
}
}
function resolveUtsFile(
dir: string,
extensions: string[] = ['.uts', '.ts', '.js']
) {
for (let i = 0; i < extensions.length; i++) {
const indexFile = path.join(dir, 'index' + extensions[i])
if (fs.existsSync(indexFile)) {
return indexFile
}
}
}
export function resolveUTSCompiler(): typeof UTSCompiler {
let compilerPath: string = ''
if (isInHBuilderX()) {
try {
compilerPath = require.resolve(
path.resolve(process.env.UNI_HBUILDERX_PLUGINS, 'uniapp-uts-v1')
)
} catch (e) {}
}
if (!compilerPath) {
try {
compilerPath = require.resolve('@dcloudio/uni-uts-v1', {
paths: [process.env.UNI_CLI_CONTEXT],
})
} catch (e) {}
}
if (!compilerPath) {
throw 'uts compiler is not found'
}
return require(compilerPath)
}
......@@ -36,10 +36,7 @@ export function parseUniExtApis(vite = true) {
parseInjects(
vite,
process.env.UNI_PLATFORM === 'h5' ? 'web' : process.env.UNI_PLATFORM,
`@/uni_modules/${uniModuleDir}` +
(vite || !process.env.UNI_UTS_PLATFORM
? ''
: `/utssdk/${process.env.UNI_UTS_PLATFORM}/index`),
`@/uni_modules/${uniModuleDir}`,
exports
)
)
......
import fs from 'fs'
import path from 'path'
import * as UTSCompiler from '@dcloudio/uni-uts-v1'
import { isInHBuilderX } from './hbx'
import { normalizePath } from './utils'
/**
* 解析 app 平台的 uts 插件,任意平台(android|ios)存在即可
* @param id
* @param importer
* @returns
*/
export function resolveUtsAppModule(id: string, importer: string) {
id = path.resolve(importer, id)
if (id.includes('utssdk') || id.includes('uni_modules')) {
const parts = normalizePath(id).split('/')
const parentDir = parts[parts.length - 2]
if (parentDir === 'uni_modules' || parentDir === 'utssdk') {
const basedir = parentDir === 'uni_modules' ? 'utssdk' : ''
if (fs.existsSync(path.resolve(id, basedir, 'index.uts'))) {
return id
}
const resolvePlatformDir = (p: typeof process.env.UNI_UTS_PLATFORM) => {
return path.resolve(id, basedir, p)
}
const extname = ['.uts']
if (resolveUtsFile(resolvePlatformDir('app-android'), extname)) {
return id
}
if (resolveUtsFile(resolvePlatformDir('app-ios'), extname)) {
return id
}
}
}
}
// 仅限 root/uni_modules/test-plugin | root/utssdk/test-plugin 格式
export function resolveUtsModule(id: string, importer: string) {
if (
process.env.UNI_PLATFORM === 'app' ||
process.env.UNI_PLATFORM === 'app-plus'
) {
return resolveUtsAppModule(id, importer)
}
id = path.resolve(importer, id)
if (id.includes('utssdk') || id.includes('uni_modules')) {
const parts = normalizePath(id).split('/')
const parentDir = parts[parts.length - 2]
if (parentDir === 'uni_modules' || parentDir === 'utssdk') {
const basedir = parentDir === 'uni_modules' ? 'utssdk' : ''
const resolvePlatformDir = (p: typeof process.env.UNI_UTS_PLATFORM) => {
return path.resolve(id, basedir, p)
}
let index = resolveUtsFile(
resolvePlatformDir(process.env.UNI_UTS_PLATFORM)
)
if (index) {
return index
}
index = path.resolve(id, basedir, 'index.uts')
if (fs.existsSync(index)) {
return index
}
}
}
}
function resolveUtsFile(
dir: string,
extensions: string[] = ['.uts', '.ts', '.js']
) {
for (let i = 0; i < extensions.length; i++) {
const indexFile = path.join(dir, 'index' + extensions[i])
if (fs.existsSync(indexFile)) {
return indexFile
}
}
}
export function resolveUTSCompiler(): typeof UTSCompiler {
let compilerPath: string = ''
if (isInHBuilderX()) {
try {
compilerPath = require.resolve(
path.resolve(process.env.UNI_HBUILDERX_PLUGINS, 'uniapp-uts-v1')
)
} catch (e) {}
}
if (!compilerPath) {
try {
compilerPath = require.resolve('@dcloudio/uni-uts-v1', {
paths: [process.env.UNI_CLI_CONTEXT],
})
} catch (e) {}
}
if (!compilerPath) {
throw 'uts compiler is not found'
}
return require(compilerPath)
}
import { isArray, hasOwn, isString, isPlainObject, isObject, capitalize, toRawType, makeMap, isFunction, isPromise, extend, remove } from '@vue/shared';
import { normalizeLocale, LOCALE_EN } from '@dcloudio/uni-i18n';
import { LINEFEED, Emitter, onCreateVueApp, invokeCreateVueAppHook } from '@dcloudio/uni-shared';
import { normalizeLocale, LOCALE_EN } from '@dcloudio/uni-i18n';
const eventChannels = {};
const eventChannelStack = [];
......@@ -952,6 +952,10 @@ function initUni(api, protocols) {
return promisify(key, wrapper(key, my[key]));
},
};
// 处理 api mp 打包后为不同js,emitter 无法共享问题
{
my.$emit = $emit;
}
return new Proxy({}, UniProxyHandlers);
}
......@@ -1106,6 +1110,7 @@ function getHostName(fromRes) {
const redirectTo = {};
let onKeyboardHeightChangeCallback;
const getProvider = initGetProvider({
oauth: ['alipay'],
share: ['alipay'],
......@@ -1206,6 +1211,19 @@ function createIntersectionObserver(component, options) {
delete options.observeAll;
}
return my.createIntersectionObserver(options);
}
function onKeyboardHeightChange(callback) {
// 与微信小程序一致仅保留最后一次监听
if (onKeyboardHeightChangeCallback) {
$off('uni:keyboardHeightChange', onKeyboardHeightChangeCallback);
}
onKeyboardHeightChangeCallback = callback;
$on('uni:keyboardHeightChange', onKeyboardHeightChangeCallback);
}
function offKeyboardHeightChange() {
// 与微信小程序一致移除最后一次监听
$off('uni:keyboardHeightChange', onKeyboardHeightChangeCallback);
onKeyboardHeightChangeCallback = undefined;
}
var shims = /*#__PURE__*/Object.freeze({
......@@ -1216,7 +1234,9 @@ var shims = /*#__PURE__*/Object.freeze({
removeStorageSync: removeStorageSync,
startGyroscope: startGyroscope,
createSelectorQuery: createSelectorQuery,
createIntersectionObserver: createIntersectionObserver
createIntersectionObserver: createIntersectionObserver,
onKeyboardHeightChange: onKeyboardHeightChange,
offKeyboardHeightChange: offKeyboardHeightChange
});
function handleNetworkInfo(fromRes, toRes) {
......
......@@ -770,6 +770,9 @@ function initCreatePage() {
onBack() {
this.$vm.$callHook(ON_BACK_PRESS);
},
onKeyboardHeight: ((res) => {
my.$emit('uni:keyboardHeightChange', res);
}),
},
__r: handleRef,
__l: handleLink,
......
......@@ -62,9 +62,9 @@ export function initCreatePage() {
onBack() {
this.$vm.$callHook(ON_BACK_PRESS)
},
onKeyboardHeight(res) {
onKeyboardHeight: ((res: unknown) => {
;(my as any).$emit('uni:keyboardHeightChange', res)
},
}) as any,
},
__r: handleRef,
__l: handleLink,
......
......@@ -62,8 +62,7 @@ export function uniUsingComponentsPlugin(
): Promise<ResolvedId | null> => {
const id = resolveUtsModule(
source,
importer || process.env.UNI_INPUT_DIR,
process.env.UNI_UTS_PLATFORM
importer || process.env.UNI_INPUT_DIR
)
if (id) {
source = id
......
......@@ -5228,7 +5228,7 @@ function injectLifecycleHook(name, hook, publicThis, instance) {
}
function initHooks(options, instance, publicThis) {
const mpType = options.mpType || publicThis.$mpType;
if (!mpType) {
if (!mpType || mpType === 'component') {
// 仅 App,Page 类型支持在 options 中配置 on 生命周期,组件可以使用组合式 API 定义页面生命周期
return;
}
......
import { isArray } from '@vue/shared'
import { runKotlinProd, runKotlinDev } from './kotlin'
import { runSwiftProd, runSwiftDev } from './swift'
export { genProxyCode, resolvePlatformIndex, resolveRootIndex } from './code'
export { resolvePackage } from './utils'
export function getCompiler(type: 'kotlin' | 'swift') {
import { genProxyCode, resolvePlatformIndex, resolveRootIndex } from './code'
import { resolvePackage } from './utils'
export async function compile(module: string) {
const pkg = resolvePackage(module)
if (!pkg) {
return
}
const deps: string[] = []
const code = await genProxyCode(module, pkg)
if (process.env.NODE_ENV !== 'development') {
// 生产模式 支持同时生成 android 和 ios 的 uts 插件
if (
process.env.UNI_UTS_PLATFORM === 'app-android' ||
process.env.UNI_UTS_PLATFORM === 'app'
) {
const filename =
resolvePlatformIndex('app-android', module, pkg) ||
resolveRootIndex(module, pkg)
if (filename) {
await getCompiler('kotlin').runProd(filename)
}
}
if (
process.env.UNI_UTS_PLATFORM === 'app-ios' ||
process.env.UNI_UTS_PLATFORM === 'app'
) {
const filename =
resolvePlatformIndex('app-ios', module, pkg) ||
resolveRootIndex(module, pkg)
if (filename) {
await getCompiler('swift').runProd(filename)
}
}
} else {
// dev 模式仅 android 支持
if (process.env.UNI_UTS_PLATFORM === 'app-android') {
const filename =
resolvePlatformIndex('app-android', module, pkg) ||
resolveRootIndex(module, pkg)
if (filename) {
deps.push(filename)
const res = await getCompiler('kotlin').runDev(filename)
if (res) {
if (isArray(res.deps) && res.deps.length) {
// 添加其他文件的依赖
deps.push(...res.deps)
}
const files: string[] = []
if (process.env.UNI_APP_CHANGED_DEX_FILES) {
try {
files.push(...JSON.parse(process.env.UNI_APP_CHANGED_DEX_FILES))
} catch (e) {}
}
if (res.dex) {
files.push(res.dex)
}
process.env.UNI_APP_CHANGED_DEX_FILES = JSON.stringify([
...new Set(files),
])
}
}
} else if (process.env.UNI_UTS_PLATFORM === 'app-ios') {
process.env.UNI_APP_IOS_UTS = 'true'
}
}
return {
code,
deps,
}
}
function getCompiler(type: 'kotlin' | 'swift') {
if (type === 'swift') {
return {
runProd: runSwiftProd,
......
......@@ -77,19 +77,31 @@ export async function runKotlinDev(
if (!compilerServer) {
return
}
const { getDefaultJar, getKotlincHome, compile, checkDependencies } =
compilerServer
const {
getDefaultJar,
getKotlincHome,
compile,
checkDependencies,
checkRResources,
} = compilerServer
let deps: string[] = []
if (checkDependencies) {
deps = await checkDeps(filename, checkDependencies)
}
let resDeps: string[] = []
if (checkRResources) {
resDeps = await checkRes(filename, checkRResources)
}
// time = Date.now()
const jarFile = resolveJarPath(kotlinFile)
const options = {
kotlinc: resolveKotlincArgs(
kotlinFile,
getKotlincHome(),
getDefaultJar().concat(resolveLibs(filename)).concat(deps)
getDefaultJar()
.concat(resolveLibs(filename))
.concat(deps)
.concat(resDeps)
),
d8: resolveD8Args(jarFile),
sourceRoot: process.env.UNI_INPUT_DIR,
......@@ -134,6 +146,7 @@ function checkDeps(
}
return Promise.resolve([])
}
function hasDeps(configJsonFile: string) {
const deps =
parseJson(fs.readFileSync(configJsonFile, 'utf8')).dependencies || []
......@@ -143,6 +156,31 @@ function hasDeps(configJsonFile: string) {
return false
}
function checkRes(
filename: string,
checkRResources: (
resDir: string
) => Promise<{ code: number; msg: string; jarPaths: string[] }>
) {
const resDir = resolveResDir(filename)
if (resDir) {
return checkRResources(resDir).then(({ code, msg, jarPaths }) => {
if (code !== 0) {
throw msg
}
return jarPaths
})
}
return Promise.resolve([])
}
function resolveResDir(filename: string) {
const resDir = path.resolve(resolveAndroidDir(filename), 'res')
if (fs.existsSync(resDir)) {
return resDir
}
}
function resolveConfigJsonFile(filename: string) {
const configJsonFile = path.resolve(
resolveAndroidDir(filename),
......@@ -281,6 +319,9 @@ interface CompilerServer {
checkDependencies?: (
configJsonPath: string
) => Promise<{ code: number; msg: string; data: string[] }>
checkRResources?: (
resDir: string
) => Promise<{ code: number; msg: string; jarPaths: string[] }>
}
function getCompilerServer(): CompilerServer | undefined {
......
......@@ -21,7 +21,10 @@ export function once<T extends (...args: any[]) => any>(
}
export const runByHBuilderX = once(() => {
return !!process.env.UNI_HBUILDERX_PLUGINS && !!process.env.RUN_BY_HBUILDERX
return (
!!process.env.UNI_HBUILDERX_PLUGINS &&
(!!process.env.RUN_BY_HBUILDERX || !!process.env.HX_Version)
)
})
export const isInHBuilderX = once(() => {
......
......@@ -41,6 +41,9 @@ export async function runDev(options: CliOptions & ServerOptions) {
if (process.env.UNI_APP_IOS_UTS) {
console.log(`\u200B` + M['uts.ios.tips'] + `\u200B`)
}
process.env.UNI_APP_CHANGED_PAGES = ''
process.env.UNI_APP_CHANGED_FILES = ''
process.env.UNI_APP_CHANGED_DEX_FILES = ''
return (
(isFirstEnd = false),
output('log', M['dev.watching.end']),
......
......@@ -6,10 +6,17 @@ import {
normalizePath,
requireResolve,
resolveUtsModule,
resolveUtsModuleProxyFile,
resolveUtsAppModule,
} from '@dcloudio/uni-cli-shared'
import { VitePluginUniResolvedOptions } from '..'
function resolveUtsModuleProxyFile(id: string, importer: string) {
const file = resolveUtsAppModule(id, importer)
if (file) {
return '\0' + file + '?uts-proxy'
}
}
export const customResolver: ResolverFunction = (updatedId, importer) => {
const utsImporter = importer
? path.dirname(importer)
......@@ -17,7 +24,7 @@ export const customResolver: ResolverFunction = (updatedId, importer) => {
const utsModuleFile =
process.env.UNI_PLATFORM === 'app'
? resolveUtsModuleProxyFile(updatedId, utsImporter)
: resolveUtsModule(updatedId, utsImporter, process.env.UNI_UTS_PLATFORM)
: resolveUtsModule(updatedId, utsImporter)
if (utsModuleFile) {
return isWindows ? normalizePath(utsModuleFile) : utsModuleFile
}
......
......@@ -42,8 +42,7 @@ export function uniResolveIdPlugin(
if (process.env.UNI_PLATFORM !== 'app') {
return resolveUtsModule(
id,
importer ? path.dirname(importer) : process.env.UNI_INPUT_DIR,
process.env.UNI_UTS_PLATFORM
importer ? path.dirname(importer) : process.env.UNI_INPUT_DIR
)
}
},
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册