From e079702951e5b3f874bb6ff042eb43fb21205c91 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Tue, 25 Oct 2022 17:01:42 +0800 Subject: [PATCH] feat(app): uts --- .eslintignore | 3 +- packages/uni-app/dist/index.d.ts | 1 + packages/uni-app/dist/index.js | 8 +- packages/uni-app/dist/utils.d.ts | 9 + packages/uni-app/dist/utils.js | 23 ++ packages/uni-app/dist/uts.d.ts | 42 +++ packages/uni-app/dist/uts.js | 186 ++++++++++ packages/uni-app/src/index.ts | 8 + packages/uni-app/src/utils.ts | 26 ++ packages/uni-app/src/uts.ts | 351 ++++++++++++++++++ packages/uni-cli-shared/lib/index.js | 3 + .../lib/uni_modules/uni_modules.js | 5 +- packages/uni-cli-shared/lib/uts/hbx.js | 8 + packages/uni-cli-shared/lib/uts/index.js | 5 + packages/uni-cli-shared/lib/uts/resolver.js | 29 ++ packages/uni-cli-shared/lib/uts/utils.js | 6 + packages/uni-cli-shared/lib/uts/uts-loader.js | 19 + packages/uni-cli-shared/lib/uts/uts.js | 97 +++++ .../vue-cli-plugin-uni/lib/app-plus/index.js | 7 + .../lib/configure-webpack.js | 20 +- 20 files changed, 839 insertions(+), 17 deletions(-) create mode 100644 packages/uni-app/dist/utils.d.ts create mode 100644 packages/uni-app/dist/utils.js create mode 100644 packages/uni-app/dist/uts.d.ts create mode 100644 packages/uni-app/dist/uts.js create mode 100644 packages/uni-app/src/utils.ts create mode 100644 packages/uni-app/src/uts.ts create mode 100644 packages/uni-cli-shared/lib/uts/hbx.js create mode 100644 packages/uni-cli-shared/lib/uts/index.js create mode 100644 packages/uni-cli-shared/lib/uts/resolver.js create mode 100644 packages/uni-cli-shared/lib/uts/utils.js create mode 100644 packages/uni-cli-shared/lib/uts/uts-loader.js create mode 100644 packages/uni-cli-shared/lib/uts/uts.js diff --git a/.eslintignore b/.eslintignore index c51ed8fb3..b2cf133a5 100644 --- a/.eslintignore +++ b/.eslintignore @@ -40,4 +40,5 @@ packages/uni-cli-shared/components/ad-fullscreen-video.vue packages/uni-cli-shared/components/ad-interactive.vue packages/uni-cli-shared/components/ad-interstitial.vue packages/uni-cli-shared/components/ad-rewarded-video.vue -packages/uni-cli-shared/lib/uni_modules/uni_modules.js +packages/uni-cli-shared/lib/uni_modules/uni_modules.js +packages/uni-cli-shared/lib/uts/uts.js diff --git a/packages/uni-app/dist/index.d.ts b/packages/uni-app/dist/index.d.ts index e127a8079..e03d6e50b 100644 --- a/packages/uni-app/dist/index.d.ts +++ b/packages/uni-app/dist/index.d.ts @@ -3,6 +3,7 @@ /// /// import { ComponentInternalInstance } from '@vue/composition-api'; +export { initUtsProxyClass, initUtsProxyFunction, initUtsIndexClassName, initUtsClassName, initUtsPackageName, } from './uts'; export declare const onShow: (callback: ((options?: App.LaunchShowOption) => void) | (() => void), target?: ComponentInternalInstance | null) => Function; export declare const onHide: (callback: (() => void) | (() => void), target?: ComponentInternalInstance | null) => Function; export declare const onLaunch: (callback: (options?: App.LaunchShowOption) => void, target?: ComponentInternalInstance | null) => Function; diff --git a/packages/uni-app/dist/index.js b/packages/uni-app/dist/index.js index c55ca2c2d..faeef4773 100644 --- a/packages/uni-app/dist/index.js +++ b/packages/uni-app/dist/index.js @@ -1,8 +1,14 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.onNavigationBarSearchInputClicked = exports.onNavigationBarSearchInputConfirmed = exports.onNavigationBarSearchInputChanged = exports.onBackPress = exports.onNavigationBarButtonTap = exports.onTabItemTap = exports.onResize = exports.onPageScroll = exports.onAddToFavorites = exports.onShareTimeline = exports.onShareAppMessage = exports.onReachBottom = exports.onPullDownRefresh = exports.onUnload = exports.onReady = exports.onLoad = exports.onInit = exports.onUniNViewMessage = exports.onThemeChange = exports.onUnhandledRejection = exports.onPageNotFound = exports.onError = exports.onLaunch = exports.onHide = exports.onShow = void 0; +exports.onNavigationBarSearchInputClicked = exports.onNavigationBarSearchInputConfirmed = exports.onNavigationBarSearchInputChanged = exports.onBackPress = exports.onNavigationBarButtonTap = exports.onTabItemTap = exports.onResize = exports.onPageScroll = exports.onAddToFavorites = exports.onShareTimeline = exports.onShareAppMessage = exports.onReachBottom = exports.onPullDownRefresh = exports.onUnload = exports.onReady = exports.onLoad = exports.onInit = exports.onUniNViewMessage = exports.onThemeChange = exports.onUnhandledRejection = exports.onPageNotFound = exports.onError = exports.onLaunch = exports.onHide = exports.onShow = exports.initUtsPackageName = exports.initUtsClassName = exports.initUtsIndexClassName = exports.initUtsProxyFunction = exports.initUtsProxyClass = void 0; var composition_api_1 = require("@vue/composition-api"); var mp = require("./mp"); +var uts_1 = require("./uts"); +Object.defineProperty(exports, "initUtsProxyClass", { enumerable: true, get: function () { return uts_1.initUtsProxyClass; } }); +Object.defineProperty(exports, "initUtsProxyFunction", { enumerable: true, get: function () { return uts_1.initUtsProxyFunction; } }); +Object.defineProperty(exports, "initUtsIndexClassName", { enumerable: true, get: function () { return uts_1.initUtsIndexClassName; } }); +Object.defineProperty(exports, "initUtsClassName", { enumerable: true, get: function () { return uts_1.initUtsClassName; } }); +Object.defineProperty(exports, "initUtsPackageName", { enumerable: true, get: function () { return uts_1.initUtsPackageName; } }); var lifecycles = []; var createLifeCycle = function (lifecycle) { lifecycles.push(lifecycle); diff --git a/packages/uni-app/dist/utils.d.ts b/packages/uni-app/dist/utils.d.ts new file mode 100644 index 000000000..64a8ce646 --- /dev/null +++ b/packages/uni-app/dist/utils.d.ts @@ -0,0 +1,9 @@ +export declare const extend: { + (target: T, source: U): T & U; + (target: T_1, source1: U_1, source2: V): T_1 & U_1 & V; + (target: T_2, source1: U_2, source2: V_1, source3: W): T_2 & U_2 & V_1 & W; + (target: object, ...sources: any[]): any; +}; +export declare const hasOwn: (val: object, key: string | symbol) => key is never; +export declare const isPlainObject: (val: unknown) => val is object; +export declare const capitalize: (str: string) => string; diff --git a/packages/uni-app/dist/utils.js b/packages/uni-app/dist/utils.js new file mode 100644 index 000000000..bb29e29c9 --- /dev/null +++ b/packages/uni-app/dist/utils.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.capitalize = exports.isPlainObject = exports.hasOwn = exports.extend = void 0; +exports.extend = Object.assign; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var hasOwn = function (val, key) { return hasOwnProperty.call(val, key); }; +exports.hasOwn = hasOwn; +var objectToString = Object.prototype.toString; +var toTypeString = function (value) { + return objectToString.call(value); +}; +var isPlainObject = function (val) { + return toTypeString(val) === '[object Object]'; +}; +exports.isPlainObject = isPlainObject; +var cacheStringFunction = function (fn) { + var cache = Object.create(null); + return (function (str) { + var hit = cache[str]; + return hit || (cache[str] = fn(str)); + }); +}; +exports.capitalize = cacheStringFunction(function (str) { return str.charAt(0).toUpperCase() + str.slice(1); }); diff --git a/packages/uni-app/dist/uts.d.ts b/packages/uni-app/dist/uts.d.ts new file mode 100644 index 000000000..b068b9fde --- /dev/null +++ b/packages/uni-app/dist/uts.d.ts @@ -0,0 +1,42 @@ +export declare function normalizeArg(arg: unknown): unknown; +interface Parameter { + name: string; + type: string; +} +interface ProxyFunctionOptions { + main?: boolean; + package: string; + class: string; + name: string; + method?: string; + companion?: boolean; + params: Parameter[]; +} +interface ProxyClassOptions { + package: string; + class: string; + constructor: { + params: Parameter[]; + }; + props: string[]; + staticProps: string[]; + methods: { + [name: string]: { + async?: boolean; + params: Parameter[]; + }; + }; + staticMethods: { + [name: string]: { + async?: boolean; + params: Parameter[]; + }; + }; +} +declare function initUtsStaticMethod(async: boolean, opts: ProxyFunctionOptions): (...args: unknown[]) => unknown; +export declare const initUtsProxyFunction: typeof initUtsStaticMethod; +export declare function initUtsProxyClass({ package: pkg, class: cls, constructor: { params: constructorParams }, methods, props, staticProps, staticMethods, }: ProxyClassOptions): any; +export declare function initUtsPackageName(name: string, is_uni_modules: boolean): string; +export declare function initUtsIndexClassName(moduleName: string, is_uni_modules: boolean): string; +export declare function initUtsClassName(moduleName: string, className: string, is_uni_modules: boolean): string; +export {}; diff --git a/packages/uni-app/dist/uts.js b/packages/uni-app/dist/uts.js new file mode 100644 index 000000000..601e8e5d8 --- /dev/null +++ b/packages/uni-app/dist/uts.js @@ -0,0 +1,186 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.initUtsClassName = exports.initUtsIndexClassName = exports.initUtsPackageName = exports.initUtsProxyClass = exports.initUtsProxyFunction = exports.normalizeArg = void 0; +var utils_1 = require("./utils"); +var callbackId = 1; +var proxy; +var callbacks = {}; +function normalizeArg(arg) { + if (typeof arg === 'function') { + var id = callbackId++; + callbacks[id] = arg; + return id; + } + else if ((0, utils_1.isPlainObject)(arg)) { + Object.keys(arg).forEach(function (name) { + ; + arg[name] = normalizeArg(arg[name]); + }); + } + return arg; +} +exports.normalizeArg = normalizeArg; +function initUtsInstanceMethod(async, opts, instanceId) { + return initProxyFunction(async, opts, instanceId); +} +function getProxy() { + if (!proxy) { + proxy = uni.requireNativePlugin('UTS-Proxy'); + } + return proxy; +} +function resolveSyncResult(res) { + if (res.errMsg) { + throw new Error(res.errMsg); + } + return res.params; +} +function invokePropGetter(args) { + return resolveSyncResult(getProxy().invokeSync(args, function () { })); +} +function initProxyFunction(async, _a, instanceId) { + var pkg = _a.package, cls = _a.class, propOrMethod = _a.name, method = _a.method, companion = _a.companion, methodParams = _a.params; + var invokeCallback = function (_a) { + var id = _a.id, name = _a.name, params = _a.params, keepAlive = _a.keepAlive; + var callback = callbacks[id]; + if (callback) { + callback.apply(void 0, params); + if (!keepAlive) { + delete callbacks[id]; + } + } + else { + console.error("".concat(pkg).concat(cls, ".").concat(propOrMethod, " ").concat(name, " is not found")); + } + }; + var baseArgs = instanceId + ? { id: instanceId, name: propOrMethod, method: methodParams } + : { + package: pkg, + class: cls, + name: method || propOrMethod, + companion: companion, + method: methodParams, + }; + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var invokeArgs = (0, utils_1.extend)({}, baseArgs, { + params: args.map(function (arg) { return normalizeArg(arg); }), + }); + if (async) { + return new Promise(function (resolve, reject) { + getProxy().invokeAsync(invokeArgs, function (res) { + if (res.type !== 'return') { + invokeCallback(res); + } + else { + if (res.errMsg) { + reject(res.errMsg); + } + else { + resolve(res.params); + } + } + }); + }); + } + return resolveSyncResult(getProxy().invokeSync(invokeArgs, invokeCallback)); + }; +} +function initUtsStaticMethod(async, opts) { + if (opts.main && !opts.method) { + if (typeof plus !== 'undefined' && plus.os.name === 'iOS') { + opts.method = 's_' + opts.name; + } + } + return initProxyFunction(async, opts, 0); +} +exports.initUtsProxyFunction = initUtsStaticMethod; +function initUtsProxyClass(_a) { + var pkg = _a.package, cls = _a.class, constructorParams = _a.constructor.params, methods = _a.methods, props = _a.props, staticProps = _a.staticProps, staticMethods = _a.staticMethods; + var baseOptions = { + package: pkg, + class: cls, + }; + var ProxyClass = (function () { + function UtsClass() { + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + var target = {}; + var instanceId = initProxyFunction(false, (0, utils_1.extend)({ name: 'constructor', params: constructorParams }, baseOptions), 0).apply(null, params); + if (!instanceId) { + throw new Error("new ".concat(cls, " is failed")); + } + return new Proxy(this, { + get: function (_, name) { + if (!target[name]) { + if ((0, utils_1.hasOwn)(methods, name)) { + var _a = methods[name], async = _a.async, params_1 = _a.params; + target[name] = initUtsInstanceMethod(!!async, (0, utils_1.extend)({ + name: name, + params: params_1, + }, baseOptions), instanceId); + } + else if (props.includes(name)) { + return invokePropGetter({ id: instanceId, name: name }); + } + } + return target[name]; + }, + }); + } + return UtsClass; + }()); + var staticMethodCache = {}; + return new Proxy(ProxyClass, { + get: function (target, name, receiver) { + if ((0, utils_1.hasOwn)(staticMethods, name)) { + if (!staticMethodCache[name]) { + var _a = staticMethods[name], async = _a.async, params = _a.params; + staticMethodCache[name] = initUtsStaticMethod(!!async, (0, utils_1.extend)({ name: name, companion: true, params: params }, baseOptions)); + } + return staticMethodCache[name]; + } + if (staticProps.includes(name)) { + return invokePropGetter((0, utils_1.extend)({ name: name, companion: true }, baseOptions)); + } + return Reflect.get(target, name, receiver); + }, + }); +} +exports.initUtsProxyClass = initUtsProxyClass; +function initUtsPackageName(name, is_uni_modules) { + if (typeof plus !== 'undefined' && plus.os.name === 'Android') { + return 'uts.sdk.' + (is_uni_modules ? 'modules.' : '') + name; + } + return ''; +} +exports.initUtsPackageName = initUtsPackageName; +function initUtsIndexClassName(moduleName, is_uni_modules) { + if (typeof plus === 'undefined') { + return ''; + } + return initUtsClassName(moduleName, plus.os.name === 'iOS' ? 'IndexSwift' : 'IndexKt', is_uni_modules); +} +exports.initUtsIndexClassName = initUtsIndexClassName; +function initUtsClassName(moduleName, className, is_uni_modules) { + if (typeof plus === 'undefined') { + return ''; + } + if (plus.os.name === 'Android') { + return className; + } + if (plus.os.name === 'iOS') { + return ('UTSSDK' + + (is_uni_modules ? 'Modules' : '') + + (0, utils_1.capitalize)(moduleName) + + (0, utils_1.capitalize)(className)); + } + return ''; +} +exports.initUtsClassName = initUtsClassName; diff --git a/packages/uni-app/src/index.ts b/packages/uni-app/src/index.ts index c9728175a..bf51a47ac 100644 --- a/packages/uni-app/src/index.ts +++ b/packages/uni-app/src/index.ts @@ -1,6 +1,14 @@ /// import { createLifeCycle as createLifeCycleBase, ComponentInternalInstance } from '@vue/composition-api' import * as mp from './mp' + +export { + initUtsProxyClass, + initUtsProxyFunction, + initUtsIndexClassName, + initUtsClassName, + initUtsPackageName, +} from './uts' const lifecycles: string[] = [] diff --git a/packages/uni-app/src/utils.ts b/packages/uni-app/src/utils.ts new file mode 100644 index 000000000..ba2c1eb8d --- /dev/null +++ b/packages/uni-app/src/utils.ts @@ -0,0 +1,26 @@ +export const extend = Object.assign + +const hasOwnProperty = Object.prototype.hasOwnProperty +export const hasOwn = ( + val: object, + key: string | symbol +): key is keyof typeof val => hasOwnProperty.call(val, key) + +const objectToString = Object.prototype.toString +const toTypeString = (value: unknown): string => + objectToString.call(value) + +export const isPlainObject = (val: unknown): val is object => + toTypeString(val) === '[object Object]' + +const cacheStringFunction = string>(fn: T): T => { + const cache: Record = Object.create(null) + return ((str: string) => { + const hit = cache[str] + return hit || (cache[str] = fn(str)) + }) as T +} + +export const capitalize = cacheStringFunction( + (str: string) => str.charAt(0).toUpperCase() + str.slice(1) +) diff --git a/packages/uni-app/src/uts.ts b/packages/uni-app/src/uts.ts new file mode 100644 index 000000000..daa9c4cda --- /dev/null +++ b/packages/uni-app/src/uts.ts @@ -0,0 +1,351 @@ +import { isPlainObject, hasOwn, extend, capitalize } from './utils' +declare const uni: any +declare const plus: any +let callbackId = 1 +let proxy: any +const callbacks: Record = {} +export function normalizeArg(arg: unknown) { + if (typeof arg === 'function') { + const id = callbackId++ + callbacks[id] = arg + return id + } else if (isPlainObject(arg)) { + Object.keys(arg).forEach((name) => { + ; (arg as any)[name] = normalizeArg((arg as any)[name]) + }) + } + return arg +} + +function initUtsInstanceMethod( + async: boolean, + opts: ProxyFunctionOptions, + instanceId: number +) { + return initProxyFunction(async, opts, instanceId) +} + +interface Parameter { + name: string + type: string +} +interface ProxyFunctionOptions { + /** + * 是否是入口类 + */ + main?: boolean + /** + * 包名 + */ + package: string + /** + * 类名 + */ + class: string + /** + * 属性名或方法名 + */ + name: string + /** + * 方法名 指定的方法名(用于 IndexSwift 静态方法,自动补充前缀 s_) + */ + method?: string + /** + * 是否伴生对象 + */ + companion?: boolean + /** + * 方法参数列表 + */ + params: Parameter[] +} + +interface ProxyClassOptions { + package: string + class: string + constructor: { + params: Parameter[] + } + props: string[] + staticProps: string[] + methods: { + [name: string]: { + async?: boolean + params: Parameter[] + } + } + staticMethods: { + [name: string]: { + async?: boolean + params: Parameter[] + } + } +} + +interface InvokeInstanceArgs { + id: number + name: string + params?: unknown[] + method?: Parameter[] +} +interface InvokeStaticArgs { + /** + * 包名 + */ + package: string + /** + * 类名 + */ + class: string + /** + * 属性名或方法名 + */ + name: string + /** + * 执行方法时的真实参数列表 + */ + params?: unknown[] + /** + * 方法定义的参数列表 + */ + method?: Parameter[] + /** + * 是否是伴生对象 + */ + companion?: boolean +} + +type InvokeArgs = InvokeInstanceArgs | InvokeStaticArgs + +interface InvokeCallbackReturnRes { + type: 'return' + params?: unknown[] + errMsg?: string +} +interface InvokeCallbackParamsRes { + type: 'params' + id: number + name: string + params: unknown[] + keepAlive?: boolean +} +interface InvokeSyncRes { + type: 'return' + errMsg?: string + params: unknown +} +type InvokeSyncCallback = (res: InvokeCallbackParamsRes) => void +type InvokeAsyncCallback = ( + res: InvokeCallbackReturnRes | InvokeCallbackParamsRes +) => void +function getProxy(): { + invokeSync: (args: InvokeArgs, callback: InvokeSyncCallback) => InvokeSyncRes + invokeAsync: (args: InvokeArgs, callback: InvokeAsyncCallback) => void +} { + if (!proxy) { + proxy = uni.requireNativePlugin('UTS-Proxy') as any + } + return proxy +} + +function resolveSyncResult(res: InvokeSyncRes) { + if (res.errMsg) { + throw new Error(res.errMsg) + } + return res.params +} + +function invokePropGetter(args: InvokeArgs) { + return resolveSyncResult(getProxy().invokeSync(args, () => { })) +} + +function initProxyFunction( + async: boolean, + { + package: pkg, + class: cls, + name: propOrMethod, + method, + companion, + params: methodParams, + }: ProxyFunctionOptions, + instanceId: number +) { + const invokeCallback = ({ + id, + name, + params, + keepAlive, + }: InvokeCallbackParamsRes) => { + const callback = callbacks[id!] + if (callback) { + callback(...params) + if (!keepAlive) { + delete callbacks[id] + } + } else { + console.error(`${pkg}${cls}.${propOrMethod} ${name} is not found`) + } + } + const baseArgs: InvokeArgs = instanceId + ? { id: instanceId, name: propOrMethod, method: methodParams } + : { + package: pkg, + class: cls, + name: method || propOrMethod, + companion, + method: methodParams, + } + return (...args: unknown[]) => { + const invokeArgs = extend({}, baseArgs, { + params: args.map((arg) => normalizeArg(arg)), + }) + if (async) { + return new Promise((resolve, reject) => { + getProxy().invokeAsync(invokeArgs, (res) => { + if (res.type !== 'return') { + invokeCallback(res) + } else { + if (res.errMsg) { + reject(res.errMsg) + } else { + resolve(res.params) + } + } + }) + }) + } + return resolveSyncResult(getProxy().invokeSync(invokeArgs, invokeCallback)) + } +} + +function initUtsStaticMethod(async: boolean, opts: ProxyFunctionOptions) { + if (opts.main && !opts.method) { + if (typeof plus !== 'undefined' && plus.os.name === 'iOS') { + opts.method = 's_' + opts.name + } + } + return initProxyFunction(async, opts, 0) +} + +export const initUtsProxyFunction = initUtsStaticMethod + +export function initUtsProxyClass({ + package: pkg, + class: cls, + constructor: { params: constructorParams }, + methods, + props, + staticProps, + staticMethods, +}: ProxyClassOptions): any { + const baseOptions = { + package: pkg, + class: cls, + } + const ProxyClass = class UtsClass { + constructor(...params: unknown[]) { + const target: Record = {} + // 初始化实例 ID + const instanceId = initProxyFunction( + false, + extend({ name: 'constructor', params: constructorParams }, baseOptions), + 0 + ).apply(null, params) as number + if (!instanceId) { + throw new Error(`new ${cls} is failed`) + } + return new Proxy(this, { + get(_, name) { + if (!target[name as string]) { + //实例方法 + if (hasOwn(methods, name)) { + const { async, params } = methods[name] + target[name] = initUtsInstanceMethod( + !!async, + extend( + { + name, + params, + }, + baseOptions + ), + instanceId + ) + } else if (props.includes(name as string)) { + // 实例属性 + return invokePropGetter({ id: instanceId, name: name as string }) + } + } + return target[name as string] + }, + }) + } + } + const staticMethodCache: Record = {} + return new Proxy(ProxyClass, { + get(target, name, receiver) { + if (hasOwn(staticMethods, name)) { + if (!staticMethodCache[name as string]) { + const { async, params } = staticMethods[name] + // 静态方法 + staticMethodCache[name] = initUtsStaticMethod( + !!async, + extend({ name, companion: true, params }, baseOptions) + ) + } + return staticMethodCache[name] + } + if (staticProps.includes(name as string)) { + // 静态属性 + return invokePropGetter( + extend({ name: name as string, companion: true }, baseOptions) + ) + } + return Reflect.get(target, name, receiver) + }, + }) +} + +export function initUtsPackageName(name: string, is_uni_modules: boolean) { + if (typeof plus !== 'undefined' && plus.os.name === 'Android') { + return 'uts.sdk.' + (is_uni_modules ? 'modules.' : '') + name + } + return '' +} + +export function initUtsIndexClassName( + moduleName: string, + is_uni_modules: boolean +) { + if (typeof plus === 'undefined') { + return '' + } + return initUtsClassName( + moduleName, + plus.os.name === 'iOS' ? 'IndexSwift' : 'IndexKt', + is_uni_modules + ) +} + +export function initUtsClassName( + moduleName: string, + className: string, + is_uni_modules: boolean +) { + if (typeof plus === 'undefined') { + return '' + } + if (plus.os.name === 'Android') { + return className + } + if (plus.os.name === 'iOS') { + return ( + 'UTSSDK' + + (is_uni_modules ? 'Modules' : '') + + capitalize(moduleName) + + capitalize(className) + ) + } + return '' +} diff --git a/packages/uni-cli-shared/lib/index.js b/packages/uni-cli-shared/lib/index.js index 287524be4..6d5b53f71 100644 --- a/packages/uni-cli-shared/lib/index.js +++ b/packages/uni-cli-shared/lib/index.js @@ -63,7 +63,10 @@ const { getPlatformUniCloud } = require('./platform') +const uts = require('./uts') + module.exports = { + uts, md5, tags, hasOwn, diff --git a/packages/uni-cli-shared/lib/uni_modules/uni_modules.js b/packages/uni-cli-shared/lib/uni_modules/uni_modules.js index e1bea8b6f..644dcef90 100644 --- a/packages/uni-cli-shared/lib/uni_modules/uni_modules.js +++ b/packages/uni-cli-shared/lib/uni_modules/uni_modules.js @@ -25,10 +25,7 @@ function parseUniExtApis(vite = true) { } const exports = (_b = (_a = JSON.parse(fs_extra_1.default.readFileSync(pkgPath, 'utf8'))) === null || _a === void 0 ? void 0 : _a.uni_modules) === null || _b === void 0 ? void 0 : _b['uni-ext-api']; if (exports) { - Object.assign(injects, 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`), exports)); + Object.assign(injects, parseInjects(vite, process.env.UNI_PLATFORM === 'h5' ? 'web' : process.env.UNI_PLATFORM, `@/uni_modules/${uniModuleDir}`, exports)); } }); return injects; diff --git a/packages/uni-cli-shared/lib/uts/hbx.js b/packages/uni-cli-shared/lib/uts/hbx.js new file mode 100644 index 000000000..29030fd99 --- /dev/null +++ b/packages/uni-cli-shared/lib/uts/hbx.js @@ -0,0 +1,8 @@ +const { + isInHBuilderX +} = require('../util') +module.exports = { + isInHBuilderX () { + return isInHBuilderX + } +} diff --git a/packages/uni-cli-shared/lib/uts/index.js b/packages/uni-cli-shared/lib/uts/index.js new file mode 100644 index 000000000..640116a14 --- /dev/null +++ b/packages/uni-cli-shared/lib/uts/index.js @@ -0,0 +1,5 @@ +const UTSResolverPlugin = require('./resolver') +const uts = require('./uts') +module.exports = Object.assign({ + UTSResolverPlugin +}, uts) diff --git a/packages/uni-cli-shared/lib/uts/resolver.js b/packages/uni-cli-shared/lib/uts/resolver.js new file mode 100644 index 000000000..a203797f4 --- /dev/null +++ b/packages/uni-cli-shared/lib/uts/resolver.js @@ -0,0 +1,29 @@ +const path = require('path') +const { + resolveUtsModule +} = require('./uts') +class UTSResolverPlugin { + apply (resolver) { + resolver.hooks.resolve.tapAsync('UTSResolverPlugin', (request, resolveContext, callback) => { + let utsModulePath = '' + if (request.request.startsWith('@/uni_modules/')) { + utsModulePath = path.resolve(process.env.UNI_INPUT_DIR, request.request.replace('@/', '')) + } else if (request.request.includes('uni_modules')) { + utsModulePath = path.resolve(request.path, request.request) + } + if (utsModulePath) { + const utsModule = resolveUtsModule(utsModulePath) + if (utsModule) { + if (process.env.UNI_PLATFORM === 'app-plus') { + request.request = utsModule + '/package.json?uts-proxy' + } else { + request.request = utsModule + } + } + } + callback() + }) + } +} + +module.exports = UTSResolverPlugin diff --git a/packages/uni-cli-shared/lib/uts/utils.js b/packages/uni-cli-shared/lib/uts/utils.js new file mode 100644 index 000000000..25e08eb9e --- /dev/null +++ b/packages/uni-cli-shared/lib/uts/utils.js @@ -0,0 +1,6 @@ +const { + normalizePath +} = require('../util') +module.exports = { + normalizePath +} diff --git a/packages/uni-cli-shared/lib/uts/uts-loader.js b/packages/uni-cli-shared/lib/uts/uts-loader.js new file mode 100644 index 000000000..4061ca564 --- /dev/null +++ b/packages/uni-cli-shared/lib/uts/uts-loader.js @@ -0,0 +1,19 @@ +const path = require('path') +const { + resolveUTSCompiler +} = require('./uts') +module.exports = function (content) { + const callback = this.async() + resolveUTSCompiler().compile(path.dirname(this.resourcePath)).then(result => { + if (result) { + result.deps.forEach((dep) => { + this.addDependency(dep) + }) + callback(null, result.code) + } else { + callback(null, '') + } + }).catch(err => { + callback(err) + }) +} diff --git a/packages/uni-cli-shared/lib/uts/uts.js b/packages/uni-cli-shared/lib/uts/uts.js new file mode 100644 index 000000000..9e63999de --- /dev/null +++ b/packages/uni-cli-shared/lib/uts/uts.js @@ -0,0 +1,97 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resolveUTSCompiler = exports.resolveUtsModule = exports.resolveUtsAppModule = void 0; +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const hbx_1 = require("./hbx"); +const utils_1 = require("./utils"); +/** + * 解析 app 平台的 uts 插件,任意平台(android|ios)存在即可 + * @param id + * @param importer + * @returns + */ +function resolveUtsAppModule(id, importer) { + id = path_1.default.resolve(importer, id); + if (id.includes('utssdk') || id.includes('uni_modules')) { + const parts = (0, utils_1.normalizePath)(id).split('/'); + const parentDir = parts[parts.length - 2]; + if (parentDir === 'uni_modules' || parentDir === 'utssdk') { + const basedir = parentDir === 'uni_modules' ? 'utssdk' : ''; + if (fs_1.default.existsSync(path_1.default.resolve(id, basedir, 'index.uts'))) { + return id; + } + const resolvePlatformDir = (p) => { + return path_1.default.resolve(id, basedir, p); + }; + const extname = ['.uts']; + if (resolveUtsFile(resolvePlatformDir('app-android'), extname)) { + return id; + } + if (resolveUtsFile(resolvePlatformDir('app-ios'), extname)) { + return id; + } + } + } +} +exports.resolveUtsAppModule = resolveUtsAppModule; +// 仅限 root/uni_modules/test-plugin | root/utssdk/test-plugin 格式 +function resolveUtsModule(id, importer) { + if (process.env.UNI_PLATFORM === 'app' || + process.env.UNI_PLATFORM === 'app-plus') { + return resolveUtsAppModule(id, importer); + } + id = path_1.default.resolve(importer, id); + if (id.includes('utssdk') || id.includes('uni_modules')) { + const parts = (0, utils_1.normalizePath)(id).split('/'); + const parentDir = parts[parts.length - 2]; + if (parentDir === 'uni_modules' || parentDir === 'utssdk') { + const basedir = parentDir === 'uni_modules' ? 'utssdk' : ''; + const resolvePlatformDir = (p) => { + return path_1.default.resolve(id, basedir, p); + }; + let index = resolveUtsFile(resolvePlatformDir(process.env.UNI_UTS_PLATFORM)); + if (index) { + return index; + } + index = path_1.default.resolve(id, basedir, 'index.uts'); + if (fs_1.default.existsSync(index)) { + return index; + } + } + } +} +exports.resolveUtsModule = resolveUtsModule; +function resolveUtsFile(dir, extensions = ['.uts', '.ts', '.js']) { + for (let i = 0; i < extensions.length; i++) { + const indexFile = path_1.default.join(dir, 'index' + extensions[i]); + if (fs_1.default.existsSync(indexFile)) { + return indexFile; + } + } +} +function resolveUTSCompiler() { + let compilerPath = ''; + if ((0, hbx_1.isInHBuilderX)()) { + try { + compilerPath = require.resolve(path_1.default.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); +} +exports.resolveUTSCompiler = resolveUTSCompiler; diff --git a/packages/vue-cli-plugin-uni/lib/app-plus/index.js b/packages/vue-cli-plugin-uni/lib/app-plus/index.js index 4e0e18430..e96f1d8f2 100644 --- a/packages/vue-cli-plugin-uni/lib/app-plus/index.js +++ b/packages/vue-cli-plugin-uni/lib/app-plus/index.js @@ -178,6 +178,13 @@ const v3 = { '../../packages/webpack-uni-app-loader/page-meta') }] }, + { + type: 'javascript/auto', + resourceQuery: /uts-proxy/, + use: [{ + loader: require.resolve('@dcloudio/uni-cli-shared/lib/uts/uts-loader.js') + }] + }, ...rules // v3 暂不支持 cache // createTemplateCacheLoader(api, diff --git a/packages/vue-cli-plugin-uni/lib/configure-webpack.js b/packages/vue-cli-plugin-uni/lib/configure-webpack.js index 0ea376e9d..a2c171b24 100644 --- a/packages/vue-cli-plugin-uni/lib/configure-webpack.js +++ b/packages/vue-cli-plugin-uni/lib/configure-webpack.js @@ -24,7 +24,8 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt isInHBuilderX, // 在 HBuilderX 的插件中 hasModule, jsPreprocessOptions, - htmlPreprocessOptions + htmlPreprocessOptions, + uts } = require('@dcloudio/uni-cli-shared') const { @@ -252,13 +253,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt .parseUniExtApis(false) const keys = Object.keys(uniExtApis) if (keys.length) { - if (process.env.UNI_PLATFORM === 'app-plus') { - keys.forEach(key => { - console.warn(`[${uniExtApis[key][0].split('/')[2]}]: uts目前仅支持vue3`) - }) - } else { - plugins.push(new webpack.ProvidePlugin(uniExtApis)) - } + plugins.push(new webpack.ProvidePlugin(uniExtApis)) } } if (!process.env.UNI_SUBPACKGE || !process.env.UNI_MP_PLUGIN) { @@ -281,7 +276,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? { patterns } : patterns)) - } catch (e) { } + } catch (e) {} } if (process.UNI_SCRIPT_ENV && Object.keys(process.UNI_SCRIPT_ENV).length) { @@ -380,7 +375,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt dir: process.env.UNI_INPUT_DIR })) } - } catch (e) { } + } catch (e) {} const resolveLoaderAlias = {} const modules = ['@vue/cli-plugin-babel', '@vue/cli-service'] @@ -415,6 +410,9 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt modules: [ process.env.UNI_INPUT_DIR, path.resolve(process.env.UNI_INPUT_DIR, 'node_modules') + ], + plugins: [ + new uts.UTSResolverPlugin() ] }, module: { @@ -433,4 +431,4 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt watchOptions: require('./util').getWatchOptions() }, platformWebpackConfig) } -} +} -- GitLab