提交 8e31cfa8 编写于 作者: fxy060608's avatar fxy060608

wip(uts): tests

上级 75b95110
import IUniLogin, { OnConnect, RegisterOptions } from '../interface'
export default class UniLogin implements IUniLogin {
//@UniJSMethod({ uiThread: true })
login(name: string, code: number) {
console.log(name, code)
}
// {"name":"fxy","callback1":{__type__:"fun",id:1},"callback2":{__type__:"fun",id:1}}
// => RegisterOptions
async register(opts: RegisterOptions) {
opts.callback1(true)
opts.callback2(true)
opts.abc.callback3(true)
}
onConnect(callback: OnConnect) {}
}
import Intent from "android.content.Intent";
import JSONObject from "com.alibaba.fastjson.JSONObject";
import UniModule from "io.dcloud.feature.uniapp.common.UniModule";
import UniJSMethod from "io.dcloud.feature.uniapp.annotation.UniJSMethod";
import UniJSCallback from "io.dcloud.feature.uniapp.bridge.UniJSCallback";
import log from "./log";
export default class TestModule implements UniLogin {
TAG = "TestModule";
static REQUEST_CODE = 1000;
//run ui thread
@UniJSMethod({ uiThread: true })
async testAsyncFunc(options: JSONObject, callback?: UniJSCallback) {
log(this.TAG, "testAsyncFunc--$options");
if (callback != null) {
const data = new JSONObject();
data["code"] = "success12312";
callback.invoke(data);
}
}
//run JS thread
@UniJSMethod({ uiThread: false })
testSyncFunc(options: JSONObject): JSONObject {
const data = new JSONObject();
data["code"] = "success456";
return data;
}
override onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
if (requestCode == TestModule.REQUEST_CODE && data.hasExtra("respond")) {
log(this.TAG, "原生页面返回----" + data.getStringExtra("respond"));
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
import Log from "android.util.Log";
export default function log(tag: string, msg: string) {
Log.e(tag, msg);
}
import Log from "android.util.Log";
export default function log(tag: string, msg: string) {
Log.e(tag, msg);
}
import { login as Login, register as Register } from '../interface.fun'
export const login: Login = (name, code) => {
console.log(name, code)
}
// import { login } from '@/uni_modules/uni-login'
// => const uniLogin = require('class')
// import { UniLogin, test } from '@/uni_modules/uni-login'
// new UniLogin()
import { RegisterOptions, OnConnect } from './interface'
export interface login {
(name: string, code: number): void
}
export interface register {
(opts: RegisterOptions): Promise<void>
}
export interface onConnect {
(callback: OnConnect): void
}
export type RegisterOptions = {
name: string
callback1: (res: boolean) => void
callback2: (res: boolean) => void
abc: {
callback3: (res: boolean) => void
}
}
export type OnConnect = () => void
export default interface IUniLogin {
login: (name: string, code: number) => void
register: (opts: RegisterOptions) => Promise<void>
onConnect: (callback: OnConnect) => void
}
// import UniLogin from '@uni_modules/uni-login'
// new UniLogin()
//
// TestSwiftComponent.swift
// DCTestSwiftPlugin
//
// Created by Dcloud-XHY on 2022/6/28.
//
import 'UIKit'
import 'MapKit'
// 必须添加 @objc(类名),编译器才会生成对应的 oc 方法
@objc(TestSwiftComponent)
class TestSwiftComponent implements DCUniComponent, MKMapViewDelegate {
mapLoadedEvent = false
showTraffic = false
mapView?: MKMapView = null
// 初始化方法
override onCreateComponent(
ref: String,
type: String,
styles: [AnyHashable: Any],
attributes: [AnyHashable: Any],
events: [Any],
uniInstance: DCUniSDKInstance
) {
// NSDictionary 转换为 swift 的 [AnyHashable : Any] ,解析参数需要使用 [AnyHashable("key")]
this.showTraffic = DCUniConvert.bool(
attributes[AnyHashable('showTraffic')] ?? false
)
}
override loadView(): UIView {
this.mapView = MKMapView.init()
return this.mapView!
}
override viewDidLoad() {
this.mapView!.delegate = this
if (this.showTraffic) {
this.mapView.showsTraffic = true
}
}
// 监听属性变化方法
override updateAttributes(attributes: [AnyHashable: Any] =new Dictionary<AnyHashable, Any>()) {
if (attributes['showsTraffic'] != null) {
this.showTraffic = DCUniConvert.bool(
attributes[AnyHashable('showsTraffic')]!
)
this.mapView.showsTraffic = this.showTraffic
}
}
// 监听注册事件方法
override addEvent(eventName: String) {
if (eventName == 'mapLoaded') {
this.mapLoadedEvent = true
}
}
override removeEvent(eventName: String) {
if (eventName == 'mapLoaded') {
this.mapLoadedEvent = false
}
}
@objc public static wx_export_method_0(): String {
return 'focus:'
}
@objc focus(options: NSDictionary) {
print(options)
}
// MARK: - MKMapViewDelegate
mapViewDidFinishLoadingMap(mapView: MKMapView) {
if (this.mapLoadedEvent) {
// 回调 event 事件
this.fireEvent('mapLoaded', { mapLoaded: 'success' })
}
}
}
//
// TestSwiftModule.swift
// DCTestSwiftPlugin
//
// Created by Dcloud-XHY on 2022/6/27.
//
//import UIKit
// 必须添加 @objc(类名),编译器才会生成对应的 oc 方法
@objc(TestSwiftModule)
class TestSwiftModule extends DCUniModule {
// 暴露异步方法供js调用:
// 1.必须添加 @objc 前缀,
// 2.使用 public static 静态方法
// 3.方法名称必须是以 wx_export_method_ 开头,后面随意拼接一个字符保证唯一性即可
// 4.方法返回实例方法的名称
// 注意点:swift 方法名称转换为 oc 方法名称时系统会自动将首个参数用 with 拼接到方法名中作为方法名的一部分 如下实例
// testAsyncFunc(options:callback:) -> testAsyncFuncWithOptions:callback
// js 中调用方法 testAsyncFuncWithOptions(options,callabck)
// 可以在参数前面加上 _ 让编译器忽略拼接参数
@objc public static wx_export_method_0() : String {
return "testAsyncFunc::"
}
// 需要暴露的实例方法
// 1.必须添加 @objc 前缀
// 2.首个参数需要添加 _ 忽略外部参数 其他参数可选
@objc testAsyncFunc(options: NSDictionary,callback?: UniModuleKeepAliveCallback) {
print(options)
if (callback != null) {
callback!("success",false)
}
}
// 暴露同步方法供js调用:
// 1.必须添加 @objc 前缀,
// 2.使用 public static 静态方法
// 3.方法名称必须是以 wx_export_method_sync_ 开头,后面随意拼接一个字符保证唯一性即可
// 4.方法返回实例方法的名称
// 注意点:swift 方法名称转换为 oc 方法名称时系统会自动将首个参数名首字符大写然后用 with 拼接到方法名中作为方法名的一部分 如下实例
// testSyncFunc(options:) -> testSyncFuncWithOptions:
// js 中调用方法 var value = testSyncFuncWithOptions(options)
@objc public static wx_export_method_sync_0() : String {
return "testSyncFunc:"
}
// 需要暴露的实例方法
// 1.必须添加 @objc 前缀
// 2.首个参数需要添加 _ 忽略外部参数
@objc testSyncFunc(options: NSDictionary) : String {
print(options);
// 暴露方法内部可以调用其他 swift 方法
return getSomeString();
}
// 不需要直接暴露给js的方法不需要添加前缀
getSomeString() : String {
return "getSomeString success"
}
}
{
"name": "UTS Plugin",
"id": "DCloud-UTSPlugin",
"version": "0.0.1",
"description": "UTS示例插件",
"main":"interface",
"_dp_type":"nativeplugin",
"_dp_nativeplugin":{
"android": {
"plugins": [
{
"type": "module",
"name": "DCloud-UTSPlugin",
"class": "io.dcloud.uniplugin.TestModule"
},
{
"type": "component",
"name": "uts-richtext",
"class": "io.dcloud.uniplugin.TestComponent"
}
],
"integrateType": "uts",
"dependencies":[
{
"id": "com.zzhoujay.richtext:richtext",
"source": "implementation 'com.zzhoujay.richtext:richtext:3.0.7'"
}
],
"minSdkVersion" : 21
}
}
}
\ No newline at end of file
import IUniLogin, { OnConnect, RegisterOptions } from '../interface.uts'
import IUniLogin from '../interface'
import { OnConnect, RegisterOptions } from '../interface'
export default class UniLogin implements IUniLogin {
//@UniJSMethod({ uiThread: true })
override login(name, code) {
console.log(name, code)
}
......
......@@ -14,6 +14,3 @@ export default interface IUniLogin {
register: (opts: RegisterOptions) => Promise<void>
onConnect: (callback: OnConnect) => void
}
// import UniLogin from '@uni_modules/uni-login'
// new UniLogin()
// 接口
interface IUniLogin {
login(): void
}
// 父类/基类
class BaseUniLogin {
register() {}
}
// 子类实现
class UniLogin extends BaseUniLogin implements IUniLogin {
// 实现接口的方法,不能写 override 关键词,因为 override 关键词仅能在实现父类的属性或方法上使用
login() {}
// 实现或覆盖父类的方法,可写可不写 override
override register(): void {}
}
async function testAsync(): Promise<number> {
return 1
}
async function main() {
const res = await testAsync()
return res
}
package index;
import ...interface.interface as IUniLogin;
import ...interface.OnConnect;
import ...interface.RegisterOptions;
open class UniLogin : IUniLogin {
override fun login(name, code) {
console.log(name, code);
}
open fun async register(opts: RegisterOptions) {
opts.callback1(true);
opts.callback2(true);
opts.abc.callback3(true);
}
override fun onConnect(callback: OnConnect) {}
}
package io.dcloud.uniplugin.TestModule;
import android.content.Intent;
import com.alibaba.fastjson.JSONObject;
import io.dcloud.feature.uniapp.common.UniModule;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.uniplugin.log.log;
open class TestModule : UniLogin {
open var TAG = "TestModule";
@UniJSMethod( uiThread = true )
open fun async testAsyncFunc(options: JSONObject, callback: UniJSCallback?) {
log(this.TAG, "testAsyncFunc--$options");
if (callback != null) {
val data = JSONObject();
data["code"] = "success12312";
callback.invoke(data);
}
}
@UniJSMethod( uiThread = false )
open fun testSyncFunc(options: JSONObject): JSONObject {
val data = JSONObject();
data["code"] = "success456";
return data;
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
if (requestCode == TestModule.REQUEST_CODE && data.hasExtra("respond")) {
log(this.TAG, "原生页面返回----" + data.getStringExtra("respond"));
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
companion object {
var REQUEST_CODE = 1000;
}
}
package io.dcloud.uniplugin.log;
import android.util.Log;
fun log(tag: String, msg: String) {
Log.e(tag, msg);
}
package test;
import android.util.Log;
fun log(tag: String, msg: String) {
Log.e(tag, msg);
}
import UIKit;
import MapKit;
@objc(TestSwiftComponent)
class TestSwiftComponent : DCUniComponent, MKMapViewDelegate {
var mapLoadedEvent = false;
var showTraffic = false;
var mapView: MKMapView? = nil;
override func onCreateComponent(_ ref: String, _ type: String, _ styles: [AnyHashable: Any], _ attributes: [AnyHashable: Any], _ events: [Any], _ uniInstance: DCUniSDKInstance) {
self.showTraffic = DCUniConvert.bool(attributes[AnyHashable("showTraffic")] ?? false);
}
override func loadView() -> UIView {
self.mapView = MKMapView.init();
return self.mapView!;
}
override func viewDidLoad() {
self.mapView!.delegate = self;
if (self.showTraffic) {
self.mapView.showsTraffic = true;
}
}
override func updateAttributes(_ attributes: [AnyHashable: Any] = Dictionary<AnyHashable, Any>()) {
if (attributes["showsTraffic"] != nil) {
self.showTraffic = DCUniConvert.bool(attributes[AnyHashable("showsTraffic")]!);
self.mapView.showsTraffic = self.showTraffic;
}
}
override func addEvent(_ eventName: String) {
if (eventName == "mapLoaded") {
self.mapLoadedEvent = true;
}
}
override func removeEvent(_ eventName: String) {
if (eventName == "mapLoaded") {
self.mapLoadedEvent = false;
}
}
@objc
public static func wx_export_method_0() -> String {
return "focus:";
}
@objc
func focus(_ options: NSDictionary) {
print(options);
}
func mapViewDidFinishLoadingMap(_ mapView: MKMapView) {
if (self.mapLoadedEvent) {
self.fireEvent("mapLoaded", [
"mapLoaded": "success"
]);
}
}
}
@objc(TestSwiftModule)
class TestSwiftModule : DCUniModule {
@objc
public static func wx_export_method_0() -> String {
return "testAsyncFunc::";
}
@objc
func testAsyncFunc(_ options: NSDictionary, _ callback: UniModuleKeepAliveCallback?) {
print(options);
if (callback != nil) {
callback!("success", false);
}
}
@objc
public static func wx_export_method_sync_0() -> String {
return "testSyncFunc:";
}
@objc
func testSyncFunc(_ options: NSDictionary) -> String {
print(options);
return getSomeString();
}
func getSomeString() -> String {
return "getSomeString success";
}
}
......@@ -11,7 +11,6 @@ import {
} from '../../types/types'
// 需要区分 android,iOS
export function uniUtsV1Plugin(): Plugin {
// TODO 1.0 版本,解析到 uts module 时,动态编译 uts ?
let moduleCode: string
return {
name: 'uni:uts-v1',
......@@ -29,7 +28,7 @@ export function uniUtsV1Plugin(): Plugin {
if (!moduleName) {
return
}
// 懒加载 uts
// 懒加载 uts 编译器
// eslint-disable-next-line no-restricted-globals
const { parse } = require('@dcloudio/uts')
const ast = await parse(code)
......@@ -39,9 +38,12 @@ export function uniUtsV1Plugin(): Plugin {
'utf8'
)
}
return moduleCode
code = moduleCode
.replace(`__MODULE_NAME__`, moduleName)
.replace(`'__MODULE_DEFINE__'`, JSON.stringify(parseModuleDefines(ast)))
// TODO compile uts
return code
},
}
}
......
import { parse, runBuild, UtsTarget } from '@dcloudio/uts'
import path from 'path'
export function getUtsCompiler(): {
parse: typeof parse
runBuild: typeof runBuild
UtsTarget: typeof UtsTarget
} {
// eslint-disable-next-line no-restricted-globals
return require('@dcloudio/uts')
}
export function compile(pluginDir: string) {
const { runBuild, UtsTarget } = getUtsCompiler()
runBuild(UtsTarget.KOTLIN, {
input: {
dir: path.join(process.env.UNI_INPUT_DIR, pluginDir),
},
output: {
dir: path.join(process.env.UNI_OUTPUT_DIR, pluginDir),
sourceMap: true,
extname: '',
},
})
}
......@@ -20,7 +20,10 @@ function resolveOptions(options: UtsOptions) {
}
if (output.sourceMap === true) {
output.sourceMap = output.outDir
} else if (output.sourceMap === false) {
} else if (
output.sourceMap === false ||
typeof output.sourceMap === 'undefined'
) {
output.sourceMap = ''
}
if (!output.imports) {
......
......@@ -27,8 +27,8 @@ export enum UtsTarget {
export type UtsMode = 'dev' | 'build'
const UtsTargetDirs = {
[UtsTarget.KOTLIN]: 'android',
[UtsTarget.SWIFT]: 'ios',
[UtsTarget.KOTLIN]: 'app-android',
[UtsTarget.SWIFT]: 'app-ios',
} as const
export const UtsTargetExtNames = {
......@@ -58,12 +58,12 @@ export interface ToOptions {
/**
* 是否生成 sourceMap,为 string 时,表示生成的 sourceMap 目标目录
*/
sourceMap: boolean | string
sourceMap?: boolean | string
/**
* sourceMap 中是否包含源码
*/
inlineSourcesContent?: boolean
extname: string
extname?: string
}
}
......@@ -99,6 +99,9 @@ function parseOptions(
if (!opts.output.dir) {
opts.output.dir = resolveDefaultOutputDir(mode, input.dir)
}
if (!opts.output.extname) {
opts.output.extname = UtsTargetExtNames[target]
}
opts.silent = opts.silent === true
return opts as ToOptions
}
......@@ -106,7 +109,7 @@ function parseOptions(
const EXTNAME = '.uts'
function resolveSrcDir(target: UtsTarget, dir: string) {
return path.join(dir, UtsTargetDirs[target] + '/src')
return path.join(dir, UtsTargetDirs[target])
}
function initInputOptions(_: UtsTarget, root: string): UtsInputOptions {
......@@ -119,12 +122,12 @@ function initInputOptions(_: UtsTarget, root: string): UtsInputOptions {
function initOutputOptions(
target: UtsTarget,
outDir: string,
sourceMap: string | boolean,
sourceMap: string | boolean | undefined,
inlineSourcesContent: boolean
): UtsOutputOptions {
return {
outDir,
sourceMap,
sourceMap: sourceMap ? sourceMap : false,
inlineSourcesContent,
extname: UtsTargetExtNames[target],
}
......@@ -227,16 +230,7 @@ interface DoBuildOptions {
function doBuild(
target: UtsTarget,
{
watch,
silent,
extname,
inputDir,
inputSrcDir,
outputDir,
input,
output,
}: DoBuildOptions
{ watch, silent, extname, inputSrcDir, input, output }: DoBuildOptions
) {
const files = glob.sync('**/*' + extname, {
absolute: true,
......@@ -252,16 +246,10 @@ function doBuild(
} as UtsResult
})
)
)
.then((res) => {
return copyAssets(UtsTarget.KOTLIN, inputDir, outputDir, extname!).then(
() => res
)
})
.then((res) => {
!silent && printUtsResults(res, watch)
return res
})
).then((res) => {
!silent && printUtsResults(res, watch)
return res
})
}
function build(target: UtsTarget, toOptions: ToOptions) {
......@@ -286,38 +274,6 @@ function build(target: UtsTarget, toOptions: ToOptions) {
})
}
function copyAssets(
target: UtsTarget,
inputDir: string,
outputDir: string,
extname: string
) {
inputDir = path.resolve(inputDir)
outputDir = path.resolve(outputDir)
const kotlinRootDir = path.join(inputDir, UtsTargetDirs[UtsTarget.KOTLIN])
const swiftRootDir = path.join(inputDir, UtsTargetDirs[UtsTarget.SWIFT])
return fs.copy(inputDir, outputDir, {
filter(src) {
if (target === UtsTarget.KOTLIN) {
if (src === swiftRootDir) {
return false
}
} else if (target === UtsTarget.SWIFT) {
if (src === kotlinRootDir) {
return false
}
}
if (path.basename(src).startsWith('.')) {
return false
}
if (fs.lstatSync(src).isDirectory()) {
return false
}
return ![extname, '.ts'].includes(path.extname(src))
},
})
}
function buildFile(
target: UtsTarget,
filename: string,
......
......@@ -19,7 +19,7 @@ export type UtsInputOptions = UtsParseOptions & {
export type UtsOutputOptions = {
outDir: string
imports?: string[]
sourceMap: boolean | string
sourceMap?: boolean | string
inlineSourcesContent?: boolean
extname: string
}
......
......@@ -18,13 +18,13 @@ parse(
runBuild(UtsTarget.KOTLIN, {
silent: false,
input: {
dir: path.resolve(projectDir, 'nativeplugins/test-uniplugin'),
dir: path.resolve(projectDir, 'uni_modules/test-uniplugin'),
extname: '.uts',
},
output: {
dir: path.resolve(
projectDir,
'unpackage/nativeplugins/test-uniplugin-android'
'unpackage/dist/app-plus/uni_modules/test-uniplugin/android'
),
sourceMap: false,
inlineSourcesContent: false,
......@@ -33,11 +33,14 @@ runBuild(UtsTarget.KOTLIN, {
runBuild(UtsTarget.SWIFT, {
silent: false,
input: {
dir: path.resolve(projectDir, 'nativeplugins/test-uniplugin'),
dir: path.resolve(projectDir, 'uni_modules/test-uniplugin'),
extname: '.uts',
},
output: {
dir: path.resolve(projectDir, 'unpackage/nativeplugins/test-uniplugin-ios'),
dir: path.resolve(
projectDir,
'unpackage/dist/app-plus/uni_modules/test-uniplugin/ios'
),
sourceMap: false,
inlineSourcesContent: false,
},
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册