diff --git a/VERSION b/VERSION index 1d5e9e0bad105584234c61dfafdc163fc6bdcbc9..5ebba4f08adf9a2c65bd6a54d3ed17792d5fe285 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.3 \ No newline at end of file +1.5.5 \ No newline at end of file diff --git a/arkoala-arkts/arkui/src/Application.ts b/arkoala-arkts/arkui/src/Application.ts index a60c065a043bdfbab3baf7906dae109210191f56..afa0423cd9b761b14fa525b8a564c4a69dc05ba9 100644 --- a/arkoala-arkts/arkui/src/Application.ts +++ b/arkoala-arkts/arkui/src/Application.ts @@ -306,7 +306,7 @@ export class Application { } // TODO: make [emitEvent] suitable to get string argument - emitEvent(type: int32, target: int32, arg0: int32, arg1: int32) { + emitEvent(type: int32, target: int32, arg0: int32, arg1: int32): string { const node = PeerNode.findPeerByNativeId(target) if (node != undefined) { try { @@ -332,6 +332,7 @@ export class Application { InteropNativeModule._NativeLog("emitEvent error: " + errorInfo(error as Object)) } } + return "0" } static createApplication(appUrl: string, params: string, useNativeLog: boolean): Application { diff --git a/arkoala-arkts/arkui/src/peers/ArkTestComponentPeer.ts b/arkoala-arkts/arkui/src/peers/ArkTestComponentPeer.ts index 431e97dff35b652f3edd28789c7205917037a342..3a7ba1c6caddfe386c9a21c4d75c743fb085084e 100644 --- a/arkoala-arkts/arkui/src/peers/ArkTestComponentPeer.ts +++ b/arkoala-arkts/arkui/src/peers/ArkTestComponentPeer.ts @@ -43,7 +43,7 @@ export class ArkTestComponentPeer extends ArkCommonMethodPeer { this.onChangeCallback = callback } logAttribute(message: string): void { - InteropNativeModule._AppendGroupedLog(1, message) + InteropNativeModule._AppendGroupedLog(0, message + "\n") } } export interface ArkTestComponentAttributes extends ArkCommonMethodAttributes { diff --git a/arkoala-arkts/arkui/src/sts/arkui.sts b/arkoala-arkts/arkui/src/sts/arkui.sts index 69aa97eceb68694645131f7c72d189853e4f7c1e..58a5b1b1a086011f649f6d5a61032d2240641850 100644 --- a/arkoala-arkts/arkui/src/sts/arkui.sts +++ b/arkoala-arkts/arkui/src/sts/arkui.sts @@ -29,9 +29,15 @@ export abstract class StructBase { console.log("Struct instantiate redirected") const instance = factory() if (builder !== undefined) builder(instance) - instance.build() + instance._build(builder, content, options) + } + build() { + throw new Error("The struct build() should never be executed directly") + } + + protected _build(style: ((instance: T)=>T)|undefined, content: (() => void)|undefined, options: OptionsT|undefined) { + throw new Error("The struct _build() must have a valid override") } - abstract build() } export enum Color { @@ -141,7 +147,7 @@ export class Text extends CommonMethod { style(instance) //content() } - + fontColor(value: Color): this { console.log("\.fontColor(", Color[value], ")") return this diff --git a/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts b/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts index 38bf4ba7c26a5b59ed2dc621fa254747539fb0e0..83016e900be785d53f0d86b590edce4597fec9ce 100644 --- a/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts +++ b/arkoala-arkts/ets-harness/src/EtsHarnessApplication.ts @@ -113,8 +113,9 @@ export class EtsHarnessApplication { return true } - emitEvent(type: int32, target: int32, arg0: int32, arg1: int32) { + emitEvent(type: int32, target: int32, arg0: int32, arg1: int32): string { const node = PeerNode.findPeerByNativeId(target) + let result = "0" switch (type) { case 1: { if (node != undefined) { @@ -124,11 +125,15 @@ export class EtsHarnessApplication { break } case 2: { - UserView.startNativeLog(1) + UserView.startNativeLog(0) break; } case 3: { - UserView.stopNativeLog(1) + UserView.stopNativeLog(0) + break; + } + case 4: { + result = UserView.getNativeLog(0) break; } default: { @@ -136,6 +141,7 @@ export class EtsHarnessApplication { break; } } + return result } updateStates(manager: StateManager, root: ComputableState ) { diff --git a/arkoala-arkts/ets-harness/src/ets/pages/case1.ets b/arkoala-arkts/ets-harness/src/ets/pages/case1.ets index 8594a52146b8ff833d3da9c834e46f83d0e43903..98f08cc78f917d946f3d32e72ad1e1411dac2a8e 100644 --- a/arkoala-arkts/ets-harness/src/ets/pages/case1.ets +++ b/arkoala-arkts/ets-harness/src/ets/pages/case1.ets @@ -5,7 +5,6 @@ struct Case1 { build() { TestComponent({ id: 42 }).onChange(() => { this.x++ - console.log("Case1 - value:" + this.x) }) .log("Case1 - value:" + this.x) } diff --git a/arkoala-arkts/ets-harness/src/ets/pages/case2.ets b/arkoala-arkts/ets-harness/src/ets/pages/case2.ets index 30529d8ff43399e65a4711f9e977a7b44a7bf47b..392f423b721054a3cb977c33ac769cf3d6a414c2 100644 --- a/arkoala-arkts/ets-harness/src/ets/pages/case2.ets +++ b/arkoala-arkts/ets-harness/src/ets/pages/case2.ets @@ -5,7 +5,6 @@ struct Case2 { build() { TestComponent({ id: 42 }).onChange(() => { this.x-- - console.log("Case2 - value:" + this.x) }) .log("Case2 - value:" + this.x) } diff --git a/arkoala-arkts/ets-harness/src/loader.ts b/arkoala-arkts/ets-harness/src/loader.ts index 586a48ad776d73d7c0253693835eb97f636d4636..4fabe956a1c2248e01cfcdcbd257aaef9e5b53e0 100644 --- a/arkoala-arkts/ets-harness/src/loader.ts +++ b/arkoala-arkts/ets-harness/src/loader.ts @@ -26,7 +26,7 @@ export interface LoaderOps { } export interface NativeControl extends LoaderOps { - _EmitEvent(type: int32, target: int32, arg0: int32, arg1: int32): void + _EmitEvent(type: int32, target: int32, arg0: int32, arg1: int32): string _RestartWith(page: string): void } @@ -46,20 +46,27 @@ export function nativeModule(): NativeControl { return theModule } +export enum TaskType { + OnChange = 1, + StartLog = 2, + StopLog = 3, + GetLog = 4, +} + export class AppControl { getLog(): string { - return "" + return nativeModule()._EmitEvent(TaskType.GetLog, -1, 0, 0) } - emitTask(type: int32, target: int32, arg1: int32, arg2: int32): AppControl { + emitTask(type: int32, target: int32, arg1: int32 = 0, arg2: int32 = 0): AppControl { nativeModule()._EmitEvent(type, target, arg1, arg2) return this } start(): AppControl { - nativeModule()._EmitEvent(2, -1, 0, 0) + nativeModule()._EmitEvent(TaskType.StartLog, -1, 0, 0) return this } stop(): AppControl { - nativeModule()._EmitEvent(3, -1, 0, 0) + nativeModule()._EmitEvent(TaskType.StopLog, -1, 0, 0) return this } nextFrame(): AppControl { diff --git a/arkoala-arkts/ets-harness/src/test_entry.ts b/arkoala-arkts/ets-harness/src/test_entry.ts index ec112fe5e519d4085f3f10c7974bb5992df68cb7..47cd0f1566f4573dda8c84920a92c6a3d06db363 100644 --- a/arkoala-arkts/ets-harness/src/test_entry.ts +++ b/arkoala-arkts/ets-harness/src/test_entry.ts @@ -1,33 +1,37 @@ import { Assert } from "@koalaui/harness" -import { AppControl } from "./loader" +import { AppControl, TaskType } from "./loader" export function entry(control: AppControl) { suite("Case1", () => { test("StateChange:Increment", () => { + const expected = "Case1 - value:1\nCase1 - value:2\nCase1 - value:3\n" + const componentId = 42 // id from Case1.TestComponent // onChange - control + const actual = control .loadPage("Case1") .start() - .emitTask(1, 42, 0, 0).nextFrame() - .emitTask(1, 42, 0, 0).nextFrame() - .emitTask(1, 42, 0, 0).nextFrame() + .emitTask(TaskType.OnChange, componentId).nextFrame() + .emitTask(TaskType.OnChange, componentId).nextFrame() + .emitTask(TaskType.OnChange, componentId).nextFrame() .stop() - let x = 3 - Assert.equal(x, 3, "StateChange test is failed!\n expected: " + 3 + "\ncurrent: " + x) + .getLog() + Assert.equal(expected, actual, "StateChange: Case1 test is failed!") }) }) suite("Case2", () => { test("StateChange:Decrement", () => { + const expected = "Case2 - value:-1\nCase2 - value:-2\nCase2 - value:-3\n" + const componentId = 42 // id from Case2.TestComponent // onChange - control + const actual = control .loadPage("Case2") .start() - .emitTask(1, 42, 0, 0).nextFrame() - .emitTask(1, 42, 0, 0).nextFrame() - .emitTask(1, 42, 0, 0).nextFrame() + .emitTask(TaskType.OnChange, componentId).nextFrame() + .emitTask(TaskType.OnChange, componentId).nextFrame() + .emitTask(TaskType.OnChange, componentId).nextFrame() .stop() - let x = -3 - Assert.equal(x, -3, "StateChange test is failed!\n expected: " + (-3) + "\ncurrent: " + x) + .getLog() + Assert.equal(expected, actual, "StateChange: Case2 test is failed!") }) }) } diff --git a/arkoala-arkts/libarkts/native/src/bridges.cc b/arkoala-arkts/libarkts/native/src/bridges.cc index 4250b79081d434b8ff41d507e66f64c13be0c7a6..1ee0b055df23f48b29912c48c27c2e2a3b9db7d2 100644 --- a/arkoala-arkts/libarkts/native/src/bridges.cc +++ b/arkoala-arkts/libarkts/native/src/bridges.cc @@ -50,6 +50,15 @@ KNativePointer impl_AnnotationAllowedAnnotations(KNativePointer contextPtr, KNat } KOALA_INTEROP_3(AnnotationAllowedAnnotations, KNativePointer, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_AnnotationAllowedAnnotationsConst(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer returnLen) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + std::size_t params_len = 0; + auto annotations = GetImpl()->AnnotationAllowedAnnotationsConst(context, node, ¶ms_len); + return new std::vector(annotations, annotations + params_len); +} +KOALA_INTEROP_3(AnnotationAllowedAnnotationsConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_AstNodeVariableConst(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); diff --git a/arkoala-arkts/libarkts/plugins/input/library.sts b/arkoala-arkts/libarkts/plugins/input/library.sts index 9d7a1f0e13cbef43c547d3047989555cab2c8ef0..84aa6aac1e9833171a875dbc184d5761468fd98f 100644 --- a/arkoala-arkts/libarkts/plugins/input/library.sts +++ b/arkoala-arkts/libarkts/plugins/input/library.sts @@ -1 +1,3 @@ export @interface Component {} + +export @interface memo {} \ No newline at end of file diff --git a/arkoala-arkts/libarkts/plugins/input/main.sts b/arkoala-arkts/libarkts/plugins/input/main.sts index bff61711a10b1179cc5d2bb790e60205e1c1d937..0a64cf195fc7de11e24bc95a5909a3ef8ac76dc3 100644 --- a/arkoala-arkts/libarkts/plugins/input/main.sts +++ b/arkoala-arkts/libarkts/plugins/input/main.sts @@ -1,4 +1,4 @@ -import { Component } from "./library" +import { Component, memo } from "./library" @interface BuilderLambda { value: string diff --git a/arkoala-arkts/libarkts/plugins/src/arkts-utils.ts b/arkoala-arkts/libarkts/plugins/src/arkts-utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..549790fd7ec1d9f633d429faaa47585ebd9e8238 --- /dev/null +++ b/arkoala-arkts/libarkts/plugins/src/arkts-utils.ts @@ -0,0 +1,28 @@ +import * as arkts from "@koalaui/libarkts" + +export function annotation(name: string): arkts.AnnotationUsageIr { + const ident: arkts.Identifier = arkts.factory.createIdentifier(name).setAnnotationUsage(); + const annotation: arkts.AnnotationUsageIr = arkts.factory.createAnnotationUsageIr(ident); + + annotation.modifiers = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_ANNOTATION_USAGE; + ident.parent = annotation; + + return annotation; +} + +export function mangle(value: string): string { + return `__${value}`; +} + +export function backingField(originalName: string): string { + return mangle(`backing_${originalName}`); +} + +export function filterDefined(value: (T | undefined)[]): T[] { + return value.filter((it: T | undefined): it is T => it != undefined); +} + +export function collect(...value: (ReadonlyArray | T | undefined)[]): T[] { + const empty: (T | undefined)[] = [] + return filterDefined(empty.concat(...value)) +} diff --git a/arkoala-arkts/libarkts/plugins/src/builder-lambda-transformer.ts b/arkoala-arkts/libarkts/plugins/src/builder-lambda-transformer.ts index 6be93bccdffd798db15b5b2012d3d0f0fb0c7cc7..e65728dba280c2f371ce5bfbd1883d5bbc9a83eb 100644 --- a/arkoala-arkts/libarkts/plugins/src/builder-lambda-transformer.ts +++ b/arkoala-arkts/libarkts/plugins/src/builder-lambda-transformer.ts @@ -31,7 +31,7 @@ function getLambdaArg(lambdaBody: arkts.AstNode, typeName: string|undefined): ar arkts.factory.createIdentifier( builderLambdaInstanceName, // TODO: it should be the return type of the function annotated with the @BuilderLambda - typeName ? arkts.factory.createTypeReference( + typeName ? arkts.factory.createTypeReferenceFromId( arkts.factory.createIdentifier( typeName ) @@ -45,7 +45,7 @@ function getLambdaArg(lambdaBody: arkts.AstNode, typeName: string|undefined): ar param ], // TODO: it should be the return type of the function annotated with the @BuilderLambda - typeName ? arkts.factory.createTypeReference( + typeName ? arkts.factory.createTypeReferenceFromId( arkts.factory.createIdentifier( typeName ) @@ -190,75 +190,142 @@ function builderLambdaReplace(leaf: arkts.CallExpression): arkts.Identifier|arkt return undefined } -export class BuilderLambdaTransformer extends AbstractVisitor { - visitor(beforeChildren: arkts.AstNode): arkts.AstNode { - const node = this.visitEachChild(beforeChildren) +function builderLambdaBodyRewrite(node: arkts.AstNode): arkts.AstNode { + if (!arkts.isArrowFunctionExpression(node)) return node; - if (!arkts.isCallExpression(node)) { - return node - } + const scriptFunc: arkts.ScriptFunction = node.scriptFunction; + if (!scriptFunc || !scriptFunc.body) return node; - if (true - && arkts.isMemberExpression(node.parent) - && arkts.isIdentifier(node.parent.property) - && arkts.isCallExpression(node.parent.parent) + const body: arkts.BlockStatement = scriptFunc.body; + const statements: arkts.AstNode[] = body.statements.map((statement: arkts.AstNode) => { + if ( + arkts.isExpressionStatement(statement) + && statement.expression + && arkts.isCallExpression(statement.expression) ) { - return node + return transformBuilderLambda(statement.expression); } + return statement; + }); + const updateBody = arkts.factory.updateBlock(body, statements); + + const signature: arkts.FunctionSignature = arkts.FunctionSignature.create(undefined, [], undefined); + const updateFunc: arkts.ScriptFunction = arkts.factory.updateScriptFunction( + scriptFunc, + updateBody, + signature, // TODO: Cannot get signature from original ScriptFunction node + scriptFunc.scriptFunctionFlags, + scriptFunc.modifiers, + false, + undefined + ); - let instanceCalls: arkts.CallExpression[] = [] - let leaf: arkts.CallExpression = node + return arkts.factory.updateArrowFunction(node, updateFunc); +} - while (true - && arkts.isMemberExpression(leaf.expression) - && arkts.isIdentifier(leaf.expression.property) - && arkts.isCallExpression(leaf.expression.object) - ) { - instanceCalls.push( - arkts.factory.createCallExpression( - leaf.expression.property, - undefined, - leaf.arguments - ) - ) - leaf = leaf.expression.object - } +function transformBuilderLambda(node: arkts.CallExpression): arkts.AstNode { + let instanceCalls: arkts.CallExpression[] = [] + let leaf: arkts.CallExpression = node - const replace = builderLambdaReplace(leaf) - if (replace === undefined) { - return node - } - - instanceCalls = instanceCalls.reverse() - let lambdaBody: arkts.Identifier | arkts.CallExpression = arkts.factory.createIdentifier(builderLambdaInstanceName) - instanceCalls.forEach((call)=> { - if (!arkts.isIdentifier(call.expression)) { - throw new Error('call expression should be identifier') - } - lambdaBody = arkts.factory.createCallExpression( - arkts.factory.createMemberExpression( - lambdaBody, - call.expression, - arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, - false, - false - ), + while (true + && arkts.isMemberExpression(leaf.expression) + && arkts.isIdentifier(leaf.expression.property) + && arkts.isCallExpression(leaf.expression.object) + ) { + instanceCalls.push( + arkts.factory.createCallExpression( + leaf.expression.property, undefined, - call.arguments + leaf.arguments ) - }) + ) + leaf = leaf.expression.object + } - const typeName = builderLambdaTypeName(leaf) - const lambdaArg = getLambdaArg(lambdaBody, typeName) + const replace = builderLambdaReplace(leaf) + if (replace === undefined) { + return node + } - return arkts.factory.updateCallExpression( - node, - replace, + instanceCalls = instanceCalls.reverse() + let lambdaBody: arkts.Identifier | arkts.CallExpression = arkts.factory.createIdentifier(builderLambdaInstanceName) + instanceCalls.forEach((call)=> { + if (!arkts.isIdentifier(call.expression)) { + throw new Error('call expression should be identifier') + } + lambdaBody = arkts.factory.createCallExpression( + arkts.factory.createMemberExpression( + lambdaBody, + call.expression, + arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, + false, + false + ), undefined, - [ - lambdaArg, - ...leaf.arguments - ] + call.arguments ) + }) + + const typeName = builderLambdaTypeName(leaf) + const lambdaArg = getLambdaArg(lambdaBody, typeName) + + let args: arkts.AstNode[] = leaf.arguments.length < 3 + ? leaf.arguments as arkts.AstNode[] + : [ + ...leaf.arguments.slice(0, 2), + builderLambdaBodyRewrite(leaf.arguments.at(2)!), + ...leaf.arguments.slice(3) // Currently, this is never reached since the maximum length of arguments is 3 + ]; + + return arkts.factory.updateCallExpression( + node, + replace, + undefined, + [ + lambdaArg, + ...args + ] + ) +} + +function isBuilderLambda(node: arkts.AstNode): boolean { + const builderLambda: arkts.AstNode | undefined = _getDeclForBuilderLambda(node); + return !!builderLambda; +} + +// TODO: temporary solution for get declaration of a builder lambda +function _getDeclForBuilderLambda(node: arkts.AstNode): arkts.AstNode | undefined { + if (!node || !arkts.isCallExpression(node)) return undefined; + + if (node.expression && arkts.isMemberExpression(node.expression)) { + const _node: arkts.MemberExpression = node.expression; + if (_node.property && arkts.isIdentifier(_node.property) && _node.property.name === "$_instantiate") { + return node; + } + if (_node.object && arkts.isCallExpression(_node.object)) { + return _getDeclForBuilderLambda(_node.object); + } + } + + return undefined; +} + +export class BuilderLambdaTransformer extends AbstractVisitor { + visitEachChild(node: arkts.AstNode): arkts.AstNode { + if (arkts.isCallExpression(node) && isBuilderLambda(node)) { + return node; + } + + return super.visitEachChild(node); + } + + visitor(beforeChildren: arkts.AstNode): arkts.AstNode { + const node = this.visitEachChild(beforeChildren) + + if (arkts.isCallExpression(node) && isBuilderLambda(node)) { + return transformBuilderLambda(node); + } + + return node; } } diff --git a/arkoala-arkts/libarkts/plugins/src/checked-stage-plugin.ts b/arkoala-arkts/libarkts/plugins/src/checked-stage-plugin.ts index ec0578ffde3afe67fb6a161e67b9d9e6a0123bfb..c7b9f14634019ca286b7452a70577082e3a213c2 100644 --- a/arkoala-arkts/libarkts/plugins/src/checked-stage-plugin.ts +++ b/arkoala-arkts/libarkts/plugins/src/checked-stage-plugin.ts @@ -2,6 +2,7 @@ import * as ts from "@koalaui/libarkts" import { PrintVisitor } from './print-visitor' import { BuilderLambdaTransformer } from './builder-lambda-transformer' import { ComponentTransformer } from './component-transformer' +import { StructTransformer } from './struct-transformer' export interface TransformerOptions { trace?: boolean, @@ -11,6 +12,13 @@ export default function exampleTransformer( userPluginOptions?: TransformerOptions ) { return (node: ts.EtsScript) => { - return new BuilderLambdaTransformer().visitor(node) + const builderLambdaTransformer = new BuilderLambdaTransformer(); + const structTransformer = new StructTransformer(); + + let script: ts.EtsScript = node; + script = builderLambdaTransformer.visitor(script) as ts.EtsScript; + script = structTransformer.visitor(script) as ts.EtsScript; + + return script; } } diff --git a/arkoala-arkts/libarkts/plugins/src/component-transformer.ts b/arkoala-arkts/libarkts/plugins/src/component-transformer.ts index eb9dea77434d7c2286f31896f1a5a76c4137f03d..10b2a6d0eafd7699766fdf15693bd79e51ec6a6a 100644 --- a/arkoala-arkts/libarkts/plugins/src/component-transformer.ts +++ b/arkoala-arkts/libarkts/plugins/src/component-transformer.ts @@ -71,6 +71,7 @@ export class ComponentTransformer extends AbstractVisitor { processComponent(node: arkts.ClassDeclaration | arkts.StructDeclaration): arkts.ClassDeclaration { const className = node.definition.name.name + arkts.GlobalInfo.getInfoInstance().add(className); this.context.componentNames.push(className) const newDefinition = arkts.factory.updateClassDefinition( @@ -85,10 +86,10 @@ export class ComponentTransformer extends AbstractVisitor { arkts.factory.createIdentifier('StructBase'), arkts.factory.createTSTypeParameterInstantiation( [ - arkts.factory.createTypeReference( + arkts.factory.createTypeReferenceFromId( arkts.factory.createIdentifier(className) ), - arkts.factory.createTypeReference( + arkts.factory.createTypeReferenceFromId( arkts.factory.createIdentifier(`__Options_${className}`) ), ] diff --git a/arkoala-arkts/libarkts/plugins/src/struct-transformer.ts b/arkoala-arkts/libarkts/plugins/src/struct-transformer.ts new file mode 100644 index 0000000000000000000000000000000000000000..1243e1c914829e87f3edf093cbf01365e32d411f --- /dev/null +++ b/arkoala-arkts/libarkts/plugins/src/struct-transformer.ts @@ -0,0 +1,183 @@ +import * as arkts from "@koalaui/libarkts" +import { AbstractVisitor } from "./AbstractVisitor"; +import { annotation } from "./arkts-utils"; + +function isCustomComponentClass(node: arkts.ClassDeclaration): boolean { + const structCollection: Set = arkts.GlobalInfo.getInfoInstance().getStructCollection(); + if (structCollection.has(node.definition.name.name)) { + return true; + } + return false; +} + +function isKnownMethodDefinition(method: arkts.MethodDefinition, name: string): boolean { + if (!method || !arkts.isMethodDefinition(method)) return false; + + // For now, we only considered matched method name. + const isNameMatched: boolean = method.name?.name === name; + return isNameMatched; +} + +function createStyleArgInBuildMethod(className: string): arkts.ETSParameterExpression { + const styleLambdaParams: arkts.ETSParameterExpression = arkts.factory.createParameterDeclaration( + arkts.factory.createIdentifier( + 'instance', + arkts.factory.createIdentifier(className), + ), + undefined + ); + + const styleLambda: arkts.ETSFunctionType = arkts.factory.createFunctionType( + arkts.FunctionSignature.create( + undefined, + [ + styleLambdaParams + ], + arkts.factory.createPrimitiveType(arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID) + ), + arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW + ); + + const optionalStyleLambda: arkts.ETSUnionType = arkts.factory.createUnionType([ + styleLambda, + arkts.factory.createUndefinedLiteral() + ]); + + const styleParam: arkts.Identifier = arkts.factory.createIdentifier( + 'style', + optionalStyleLambda + ); + + const param = arkts.factory.createParameterDeclaration(styleParam, undefined); + param.annotations = [annotation("memo")]; + + return param; +} + +function createContentArgInBuildMethod(): arkts.ETSParameterExpression { + const contentLambda: arkts.ETSFunctionType = arkts.factory.createFunctionType( + arkts.FunctionSignature.create( + undefined, + [], + arkts.factory.createPrimitiveType(arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID) + ), + arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW + ); + + const optionalContentLambda: arkts.ETSUnionType = arkts.factory.createUnionType([ + contentLambda, + arkts.factory.createUndefinedLiteral() + ]); + + const contentParam: arkts.Identifier = arkts.factory.createIdentifier( + 'content', + optionalContentLambda + ); + + const param = arkts.factory.createParameterDeclaration(contentParam, undefined); + param.annotations = [annotation("memo")]; + + return param; +} + +function createInitializerArgInBuildMethod(className: string): arkts.ETSParameterExpression { + return arkts.factory.createParameterDeclaration( + arkts.factory.createIdentifier( + 'initializers', + arkts.factory.createTypeReferenceFromId( + arkts.factory.createIdentifier(`__Options_${className}`) + ) + ).setOptional(true), + undefined + ); +} + +function prepareArgsInBuildMethod(className: string): arkts.ETSParameterExpression[] { + return [ + createStyleArgInBuildMethod(className), + createContentArgInBuildMethod(), + createInitializerArgInBuildMethod(className) + ]; +} + +function transformBuildMethod( + method: arkts.MethodDefinition, + className: string +): arkts.MethodDefinition { + const updateKey: arkts.Identifier = arkts.factory.createIdentifier( + '_build' + ); + + const scriptFunction: arkts.ScriptFunction = method.scriptFunction; + + const params: arkts.ETSParameterExpression[] = prepareArgsInBuildMethod(className); + + const signature: arkts.FunctionSignature = arkts.FunctionSignature.create( + undefined, + params, + undefined + ); + const updateScriptFunction = arkts.factory.createScriptFunction( + scriptFunction.body, + signature, + scriptFunction.scriptFunctionFlags, + scriptFunction.modifiers, + false, + undefined + ); + + updateScriptFunction.annotations = [annotation("memo")]; + + // TODO: Currently, just return method itself. Remove this once createMethodDefinition is ready. + return arkts.factory.createMethodDefinition( + arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD, + updateKey, + arkts.factory.createFunctionExpression(updateScriptFunction), + arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED, + false + ); +} + +function tranformClassMembers(node: arkts.ClassDeclaration): arkts.ClassDeclaration { + const definition: arkts.ClassDefinition = node.definition; + const className: string = node.definition.name.name; + + const updateMembers: arkts.AstNode[] = definition.members.map((member: arkts.AstNode) => { + if (arkts.isMethodDefinition(member) && isKnownMethodDefinition(member, "constructor")) { + return arkts.factory.createMethodDefinition( + arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_CONSTRUCTOR, + member.name, + arkts.factory.createFunctionExpression(member.scriptFunction), + arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR, + false + ); + } + if (arkts.isMethodDefinition(member) && isKnownMethodDefinition(member, "build")) { + return transformBuildMethod(member, className); + } + + return member; + }); + + const updateClassDef: arkts.ClassDefinition = arkts.factory.updateClassDefinition( + definition, + definition.name, + updateMembers, + definition.modifiers, + arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, + definition.typeParamsDecl, + definition.superClass + ); + + return arkts.factory.updateClassDeclaration(node, updateClassDef); +} + +export class StructTransformer extends AbstractVisitor { + visitor(beforeChildren: arkts.AstNode): arkts.AstNode { + const node = this.visitEachChild(beforeChildren); + if (arkts.isClassDeclaration(node) && isCustomComponentClass(node)) { + return tranformClassMembers(node); + } + return node; + } +} diff --git a/arkoala-arkts/libarkts/plugins/tsconfig.json b/arkoala-arkts/libarkts/plugins/tsconfig.json index d0ce6f2228dd65d7edd13be46f938c0f80e98558..a460c9048c088fdb8c876ec39edb9be7214c9c71 100644 --- a/arkoala-arkts/libarkts/plugins/tsconfig.json +++ b/arkoala-arkts/libarkts/plugins/tsconfig.json @@ -14,5 +14,7 @@ "./src/print-visitor.ts", "./src/builder-lambda-transformer.ts", "./src/component-transformer.ts", + "./src/struct-transformer.ts", + "./src/arkts-utils.ts", ] } diff --git a/arkoala-arkts/libarkts/src/Es2pandaNativeModule.ts b/arkoala-arkts/libarkts/src/Es2pandaNativeModule.ts index e62809f69870d79fb9ddeab09c92f0c51464216b..f3fe48606fcdec90e0d1406ceee7f92707b8e280 100644 --- a/arkoala-arkts/libarkts/src/Es2pandaNativeModule.ts +++ b/arkoala-arkts/libarkts/src/Es2pandaNativeModule.ts @@ -53,6 +53,9 @@ export class Es2pandaNativeModule { _AnnotationAllowedAnnotations(context: KPtr, node: KPtr, returnLen: KPtr): KPtr { throw new Error("Not implemented") } + _AnnotationAllowedAnnotationsConst(context: KPtr, node: KPtr, returnLen: KPtr): KPtr { + throw new Error("Not implemented") + } _AstNodeRebind(context: KPtr, node: KPtr): void { throw new Error("Not implemented") } @@ -164,6 +167,9 @@ export class Es2pandaNativeModule { _ScriptFunctionBody(context: KPtr, node: KPtr): KPtr { throw new Error("Not implemented") } + _ScriptFunctionAnnotations(context: KPtr, node: KPtr, returnLen: KPtr): KPtr { + throw new Error("Not implemented") + } _ScriptFunctionSetIdent(context: KPtr, ast: KPtr, id: KPtr): KPtr { throw new Error("Not implemented") } @@ -176,6 +182,9 @@ export class Es2pandaNativeModule { _ScriptFunctionSetScope(context: KPtr, ast: KPtr, scope: KPtr): KPtr { throw new Error("Not implemented") } + _ScriptFunctionSetAnnotations(context: KPtr, ast: KPtr, annotations: KPtrArray, annotationsLen: KInt): KPtr { + throw new Error("Not implemented") + } _ScriptFunctionDeclareConst(context: KPtr, node: KPtr): KBoolean { throw new Error("Not implemented") } @@ -191,6 +200,12 @@ export class Es2pandaNativeModule { _ScriptFunctionAddFlag(context: KPtr, node: KPtr, flags: KInt): void { throw new Error("Not implemented") } + _ClassPropertyAnnotations(context: KPtr, node: KPtr, returnLen: KPtr): KPtr { + throw new Error("Not implemented") + } + _ClassPropertySetAnnotations(context: KPtr, ast: KPtr, annotations: KPtrArray, annotationsLen: KInt): KPtr { + throw new Error("Not implemented") + } _UpdateBlockStatement(context: KPtr, original: KPtr, statementList: KPtrArray, statementListLen: KInt): KPtr { throw new Error("Not implemented") } @@ -392,6 +407,12 @@ export class Es2pandaNativeModule { _ETSParameterExpressionIdent(context: KPtr, node: KPtr): KPtr { throw new Error("Not implemented") } + _ETSParameterExpressionAnnotations(context: KPtr, node: KPtr, returnLen: KPtr): KPtr { + throw new Error("Not implemented") + } + _ETSParameterExpressionSetAnnotations(context: KPtr, ast: KPtr, annotations: KPtrArray, annotationsLen: KInt): KPtr { + throw new Error("Not implemented") + } _CreateTSTypeParameterDeclaration(context: KPtr, params: KPtrArray, paramsLen: KInt, requiredParams: KInt): KPtr { throw new Error("Not implemented") } @@ -551,6 +572,25 @@ export class Es2pandaNativeModule { _DeclarationFromIdentifier(context: KPtr, identifier: KPtr): KPtr { throw new Error("Not implemented") } + _IsTSInterfaceDeclaration(ast: KNativePointer): KBoolean { + throw new Error("Not implemented") + } + + _IsAnnotationDeclaration(ast: KNativePointer): KBoolean { + throw new Error("Not implemented") + } + + _IsAnnotationUsage(ast: KNativePointer): KBoolean { + throw new Error("Not implemented") + } + + _IsClassProperty(ast: KNativePointer): KBoolean { + throw new Error("Not implemented") + } + + _CreateAnnotationUsageIr(context: KPtr, ast: KPtr): KPtr { + throw new Error("Not implemented") + } } export function initEs2panda(): Es2pandaNativeModule { diff --git a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts index ff36ada6fe71586ed48aadfffa6919ab11c5a85b..778cb68cd88abd0fc89f5238275434e26e481e93 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeFactory.ts @@ -15,12 +15,14 @@ import { updateNodeByNode } from "../utilities/private" import { + AnnotationUsageIr, ArrowFunctionExpression, BinaryExpression, BlockStatement, CallExpression, ClassDeclaration, ClassDefinition, + ClassProperty, ETSFunctionType, EtsImportDeclaration, ETSParameterExpression, @@ -46,6 +48,7 @@ import { TSTypeParameter, TSTypeParameterDeclaration, TSTypeParameterInstantiation, + UndefinedLiteral, VariableDeclaration, VariableDeclarator } from "../types" @@ -238,6 +241,12 @@ export const factory = { get updateClassDefinition() { return compose(ClassDefinition.create) }, + get createClassProperty() { + return ClassProperty.create + }, + get updateClassProperty() { + return compose(ClassProperty.create) + }, get createFunctionType() { return ETSFunctionType.create }, @@ -274,4 +283,16 @@ export const factory = { get updateInterfaceDeclaration() { return compose(TSInterfaceDeclaration.create) }, + get createUndefinedLiteral() { + return UndefinedLiteral.create + }, + get updateUndefinedLiteral() { + return compose(UndefinedLiteral.create) + }, + get createAnnotationUsageIr() { + return AnnotationUsageIr.create + }, + get updateAnnotationUsageIr() { + return compose(UndefinedLiteral.create) + }, } diff --git a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeTests.ts b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeTests.ts index 07750fe2ffb1e9e3c7d35614b9f4485866415eaf..70089c66931ac142d162cb7c5df34785782b3abc 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/factory/nodeTests.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/factory/nodeTests.ts @@ -1,4 +1,7 @@ +import { global } from "../static/global" import { + AnnotationDeclaration, + AnnotationUsageIr, ArrowFunctionExpression, BlockStatement, CallExpression, @@ -14,11 +17,29 @@ import { ScriptFunction, StringLiteral, StructDeclaration, + TSInterfaceDeclaration, VariableDeclaration, + ClassProperty } from "../types" import { MemberExpression } from "../to-be-generated/MemberExpression" import { AstNode } from "../peers/AstNode" +export function isClassProperty(node: AstNode): node is ClassProperty { + return global.es2panda._IsClassProperty(node.peer); +} + +export function isAnnotationUsage(node: AstNode): node is AnnotationUsageIr { + return global.es2panda._IsAnnotationUsage(node.peer); +} + +export function isAnnotationDeclaration(node: AstNode): node is AnnotationDeclaration { + return global.es2panda._IsAnnotationDeclaration(node.peer); +} + +export function isTSInterfaceDeclaration(node: AstNode): node is TSInterfaceDeclaration { + return global.es2panda._IsTSInterfaceDeclaration(node.peer); +} + export function isIdentifier(node: AstNode): node is Identifier { return node instanceof Identifier } diff --git a/arkoala-arkts/libarkts/src/arkts-api/types.ts b/arkoala-arkts/libarkts/src/arkts-api/types.ts index 10b6b5197ea8d416e498ade67fe08e32b860a421..a3168d27ba4933c04a9647f2711d32ffb8dac6a1 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/types.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/types.ts @@ -19,6 +19,7 @@ import { KBoolean, KInt, KNativePointer as KPtr, nullptr } from "@koalaui/intero import { Es2pandaClassDefinitionModifiers, Es2pandaContextState, + Es2pandaExpressionParseFlags, Es2pandaIdentifierFlags, Es2pandaImportKinds, Es2pandaMethodDefinitionKind, @@ -298,6 +299,7 @@ export class ETSTypeReferencePart extends AstNode { constructor(peer: KPtr) { assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_ETS_TYPE_REFERENCE_PART) super(peer) + this.typeName = unpackNonNullableNode(global.generatedEs2panda._ETSTypeReferencePartName(global.context, this.peer)); } // TODO: support type params and prev @@ -317,7 +319,7 @@ export class ETSTypeReferencePart extends AstNode { ) } - // readonly typeName: Identifier + readonly typeName: Identifier } export class TSUnionType extends AstNode { @@ -396,9 +398,18 @@ export class Identifier extends AstNode { static create( name: string, - typeAnnotation?: AstNode + typeAnnotation?: AstNode, + isAnnotation?: boolean ): Identifier { - if (typeAnnotation === undefined) { + if (isAnnotation) { + return new Identifier( + global.es2panda._ETSParserCreateExpression( + global.context, + passString(name), + Es2pandaExpressionParseFlags.EXPRESSION_PARSE_FLAGS_ACCEPT_COMMA + ) + ) + } else if (typeAnnotation === undefined) { return new Identifier( global.es2panda._CreateIdentifier1(global.context, passString(name)) ) @@ -409,6 +420,16 @@ export class Identifier extends AstNode { } } + setOptional(optional: boolean): Identifier { + global.generatedEs2panda._IdentifierSetOptional(global.context, this.peer, optional) + return this + } + + setAnnotationUsage(): Identifier { + global.generatedEs2panda._IdentifierSetAnnotationUsage(global.context, this.peer); + return this; + } + protected override dumpMessage(): string { return ` ` } @@ -554,6 +575,12 @@ export class ScriptFunction extends AstNode { return new ScriptFunction(peer) } + setIdent(id: Identifier): ScriptFunction { + assertValidPeer(id.peer, Es2pandaAstNodeType.AST_NODE_TYPE_IDENTIFIER); + global.generatedEs2panda._ScriptFunctionSetIdent(global.context, this.peer, id.peer); + return this; + } + protected override dumpMessage(): string { const scriptFunctionFlags = global.generatedEs2panda._ScriptFunctionFlagsConst(global.context, this.peer) return ` ` @@ -596,6 +623,23 @@ export class ScriptFunction extends AstNode { // readonly signature: FunctionSignature readonly scriptFunctionFlags: KInt readonly ident?: Identifier + + get annotations(): AnnotationUsageIr[] { + return unpackNodeArray(global.es2panda._ScriptFunctionAnnotations( + global.context, + this.peer, + nullptr + )) as AnnotationUsageIr[]; + } + + set annotations(newAnnotations: AnnotationUsageIr[]) { + global.es2panda._ScriptFunctionSetAnnotations( + global.context, + this.peer, + passNodeArray(newAnnotations), + newAnnotations.length + ); + } } export class ArrowFunctionExpression extends AstNode { @@ -721,6 +765,23 @@ export class ETSParameterExpression extends AstNode { ) ) } + + get annotations(): AnnotationUsageIr[] { + return unpackNodeArray(global.es2panda._ETSParameterExpressionAnnotations( + global.context, + this.peer, + nullptr + )) as AnnotationUsageIr[]; + } + + set annotations(newAnnotations: AnnotationUsageIr[]) { + global.es2panda._ETSParameterExpressionSetAnnotations( + global.context, + this.peer, + passNodeArray(newAnnotations), + newAnnotations.length + ); + } } export class TSTypeParameterDeclaration extends AstNode { @@ -933,10 +994,20 @@ export class ClassStaticBlock extends AstNode { } export class MethodDefinition extends AstNode { - constructor(peer: KPtr) { + constructor(peer: KPtr, key?: KPtr) { assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_METHOD_DEFINITION) super(peer) + this.kind = global.generatedEs2panda._MethodDefinitionKindConst(global.context, this.peer); this.scriptFunction = unpackNonNullableNode(global.generatedEs2panda._MethodDefinitionFunction(global.context, this.peer)) + assertValidPeer(this.scriptFunction.peer, Es2pandaAstNodeType.AST_NODE_TYPE_SCRIPT_FUNCTION); + + // Somehow the scriptFunction cannot attach method's key to its ident after checker + if (key) { + assertValidPeer(key, Es2pandaAstNodeType.AST_NODE_TYPE_IDENTIFIER); + const _name = unpackNonNullableNode(key); + this.scriptFunction = this.scriptFunction.setIdent(_name as Identifier); + } + this.name = unpackNonNullableNode(global.generatedEs2panda._ScriptFunctionId(global.context, this.scriptFunction.peer)) this.kind = global.generatedEs2panda._MethodDefinitionKindConst(global.context, this.peer) } @@ -956,13 +1027,19 @@ export class MethodDefinition extends AstNode { passNode(value), modifiers, isComputed - ) + ), + key.peer ) } + // TODO: does not work + isConstructor(): boolean { + return global.generatedEs2panda._MethodDefinitionIsConstructorConst(global.context, this.peer); + } + + readonly kind: Es2pandaMethodDefinitionKind; readonly scriptFunction: ScriptFunction readonly name: Identifier - readonly kind: Es2pandaMethodDefinitionKind } export class ClassElement extends AstNode { @@ -980,6 +1057,7 @@ export class ClassProperty extends ClassElement { constructor(peer: KPtr) { assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_CLASS_PROPERTY) super(peer) + this.typeAnnotation = unpackNonNullableNode(global.generatedEs2panda._ClassPropertyTypeAnnotationConst(global.context, this.peer)); } static create( @@ -1000,6 +1078,25 @@ export class ClassProperty extends ClassElement { ) ) } + + get annotations(): AnnotationUsageIr[] { + return unpackNodeArray(global.es2panda._ScriptFunctionAnnotations( + global.context, + this.peer, + nullptr + )) as AnnotationUsageIr[]; + } + + set annotations(newAnnotations: AnnotationUsageIr[]) { + global.es2panda._ScriptFunctionSetAnnotations( + global.context, + this.peer, + passNodeArray(newAnnotations), + newAnnotations.length + ); + } + + readonly typeAnnotation: ETSTypeReference; } export class VariableDeclaration extends AstNode { @@ -1067,6 +1164,7 @@ export class SuperExpression extends AstNode { constructor(peer: KPtr) { assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_SUPER_EXPRESSION) super(peer) + this.id = unpackNonNullableNode(global.generatedEs2panda._TSInterfaceDeclarationId(global.context, this.peer)); } static create( @@ -1077,6 +1175,8 @@ export class SuperExpression extends AstNode { ) ) } + + readonly id?: Identifier; } export class ImportSource extends ArktsObject { @@ -1165,8 +1265,16 @@ export class AnnotationUsageIr extends AstNode { this.properties = unpackNodeArray(global.generatedEs2panda._AnnotationUsageIrPropertiesConst(global.context, this.peer)) } - // TODO: - // static create + static create( + annoIdent: AstNode + ): AnnotationUsageIr { + return new AnnotationUsageIr( + global.es2panda._CreateAnnotationUsageIr( + global.context, + passNode(annoIdent) + ) + ); + } readonly expr: AstNode readonly properties: readonly ClassProperty[] @@ -1225,4 +1333,28 @@ export class UndefinedLiteral extends AstNode { assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_UNDEFINED_LITERAL) super(peer) } + + static create(): UndefinedLiteral { + return new UndefinedLiteral( + global.generatedEs2panda._CreateUndefinedLiteral(global.context) + ) + } +} + +export class AnnotationDeclaration extends AstNode { + constructor(peer: KPtr) { + assertValidPeer(peer, Es2pandaAstNodeType.AST_NODE_TYPE_ANNOTATION_DECLARATION); + super(peer) + } + + static create( + expr: AstNode + ): AnnotationDeclaration { + return new AnnotationDeclaration ( + global.generatedEs2panda._CreateAnnotationDeclaration( + global.context, + passNode(expr) + ) + ) + } } diff --git a/arkoala-arkts/libarkts/src/arkts-api/utilities/public.ts b/arkoala-arkts/libarkts/src/arkts-api/utilities/public.ts index dbea933f3c14c53834281e4863a39e766a3d4279..7231cc0f59cd8d95dd3563cc5b03629a3ade71b3 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/utilities/public.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/utilities/public.ts @@ -16,12 +16,11 @@ import { global } from "../static/global" import { throwError } from "../../utils" import { KNativePointer, nullptr, withStringResult } from "@koalaui/interop" -import { AnnotationUsageIr, MethodDefinition } from "../types" import { passNode, unpackNodeArray, unpackNonNullableNode } from "./private" import { isClassDefinition, isFunctionDeclaration, isScriptFunction } from "../factory/nodeTests" import { Es2pandaContextState } from "../../generated/Es2pandaEnums" import { AstNode } from "../peers/AstNode" -import { Identifier } from "../types" +import { AnnotationUsageIr } from "../types" export function proceedToState(state: Es2pandaContextState): void { if (state <= global.es2panda._ContextState(global.context)) { diff --git a/arkoala-arkts/libarkts/src/arkts-api/visitor.ts b/arkoala-arkts/libarkts/src/arkts-api/visitor.ts index f114ccef781eca77d431c1a79213f0a06b1baa31..622448e3856bc4dc82e6cbe07fc5dee781e4896b 100644 --- a/arkoala-arkts/libarkts/src/arkts-api/visitor.ts +++ b/arkoala-arkts/libarkts/src/arkts-api/visitor.ts @@ -38,6 +38,53 @@ import { MemberExpression } from "./to-be-generated/MemberExpression" type Visitor = (node: AstNode) => AstNode +export interface DoubleNode { + originNode: AstNode; + translatedNode: AstNode; +} + +export class StructInfo { + stateVariables: Set = new Set(); +} + +export class GlobalInfo { + private _structCollection: Set; + private static instance: GlobalInfo; + private _structMap: Map; + + private constructor() { + this._structCollection = new Set(); + this._structMap = new Map(); + } + + public static getInfoInstance(): GlobalInfo { + if (!this.instance) { + this.instance = new GlobalInfo(); + } + return this.instance; + } + + public add(str: string): void { + this._structCollection.add(str); + } + + public getStructCollection(): Set { + return this._structCollection; + } + + public getStructInfo(structName: string): StructInfo { + const structInfo = this._structMap.get(structName); + if (!structInfo) { + return new StructInfo(); + } + return structInfo; + } + + public setStructInfo(structName: string, info: StructInfo): void { + this._structMap.set(structName, info); + } +} + // TODO: rethink (remove as) function nodeVisitor(node: T, visitor: Visitor): T { if (node === undefined) { diff --git a/arkoala-arkts/loader/src/loader.ts b/arkoala-arkts/loader/src/loader.ts index 8936e229e7ea669915fc0c9c0b484149afd0acc5..f66b0a9775d09a10bf5c11fe79d032e68ed46984 100644 --- a/arkoala-arkts/loader/src/loader.ts +++ b/arkoala-arkts/loader/src/loader.ts @@ -46,7 +46,7 @@ export interface NativeControl extends LoaderOps { _SetVsyncCallback(pipeline: KPointer): void _VSyncAwait(pipeline: KPointer): Promise _UnblockVsyncWait(pipeline: KPointer): void - _EmitEvent(type: int32, target: int32, arg0: int32, arg1: int32): void + _EmitEvent(type: int32, target: int32, arg0: int32, arg1: int32): string } function callCallback(id: int32, args: KUint8ArrayPtr, length: int32): int32 { diff --git a/arkoala-arkts/trivial/user/src/sts/hello.sts b/arkoala-arkts/trivial/user/src/sts/hello.sts index 41c42c50e77df8a917c5b8494489635b438fcf3a..1923eb273dc52ae930be03dfe16adb20d8893518 100644 --- a/arkoala-arkts/trivial/user/src/sts/hello.sts +++ b/arkoala-arkts/trivial/user/src/sts/hello.sts @@ -1,7 +1,7 @@ import { Text } from "@ohos.arkui" import { Column, ColumnOptions } from "@ohos.arkui" import { Button } from "@ohos.arkui" -import { Component, State, Entry } from "@ohos.arkui" +import { Component, State, Entry, memo } from "@ohos.arkui" import { Color } from "@ohos.arkui" @Entry diff --git a/arkoala/arkui-common/package.json b/arkoala/arkui-common/package.json index eaf72b00b033defba402371845e920017305e761..f67bcb9d5b8c78d3fd59b510a1a56a89607729f1 100644 --- a/arkoala/arkui-common/package.json +++ b/arkoala/arkui-common/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/arkui-common", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "build/lib/src/index.js", "exports": { @@ -53,9 +53,9 @@ }, "keywords": [], "dependencies": { - "@koalaui/common": "1.5.3+devel", - "@koalaui/compat": "1.5.3+devel", - "@koalaui/runtime": "1.5.3+devel", + "@koalaui/common": "1.5.5+devel", + "@koalaui/compat": "1.5.5+devel", + "@koalaui/runtime": "1.5.5+devel", "@koalaui/ets-tsc": "4.9.5-r4", "@koalaui/fast-arktsc": "next" } diff --git a/arkoala/arkui/package.json b/arkoala/arkui/package.json index d7f5d0a206169fed8c0c0337a6292733cdab41d3..55c80acfa8a88843479ab8a0b16a2a68975d39b4 100644 --- a/arkoala/arkui/package.json +++ b/arkoala/arkui/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/arkoala-arkui", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "build/lib/src/index.js", "exports": { @@ -45,10 +45,10 @@ }, "keywords": [], "dependencies": { - "@koalaui/common": "1.5.3+devel", - "@koalaui/runtime": "1.5.3+devel", + "@koalaui/common": "1.5.5+devel", + "@koalaui/runtime": "1.5.5+devel", "@koalaui/arkoala": "1.4.1+devel", - "@koalaui/arkui-common": "1.5.3+devel", + "@koalaui/arkui-common": "1.5.5+devel", "@koalaui/ets-tsc": "4.9.5-r4", "media-query-parser": "^2.0.2", "commander": "10.0.1" diff --git a/arkoala/ets-plugin/package.json b/arkoala/ets-plugin/package.json index 1672624374e1b264c82ac8a589a41f7bb946ebf4..aa39e9813b7f109c2ae5d328acec934b789df76d 100644 --- a/arkoala/ets-plugin/package.json +++ b/arkoala/ets-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/ets-plugin", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "build/lib/src/index.js", "types": "build/lib/src/index.d.ts", diff --git a/incremental/build-common/package.json b/incremental/build-common/package.json index 4fbd620d677ea15797fddfdb24bf48eff22957be..6c39c39b5f592863ffa4fbb6501f93db529be0af 100644 --- a/incremental/build-common/package.json +++ b/incremental/build-common/package.json @@ -1,8 +1,11 @@ { "name": "@koalaui/build-common", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "files": [ "tsconfig.json" - ] + ], + "scripts": { + "compile": "" + } } \ No newline at end of file diff --git a/incremental/common/package.json b/incremental/common/package.json index 5eb5658c8229b3796c602e7abe37f1d5925be2a8..5a948a90bde5941757a5b78591aee956d0a169c6 100644 --- a/incremental/common/package.json +++ b/incremental/common/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/common", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "build/lib/src/index.js", "types": "./index.d.ts", @@ -43,7 +43,7 @@ }, "keywords": [], "dependencies": { - "@koalaui/compat": "1.5.3+devel" + "@koalaui/compat": "1.5.5+devel" }, "devDependencies": { "@ohos/hypium": "1.0.6", diff --git a/incremental/compat/package.json b/incremental/compat/package.json index 62ad8d61d6236a456fcfba402e31904d411ef367..81a3dea9b011f9a01f003539edefc7188f42dce3 100644 --- a/incremental/compat/package.json +++ b/incremental/compat/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/compat", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "build/src/index.js", "types": "build/src/index.d.ts", diff --git a/incremental/compiler-plugin/package.json b/incremental/compiler-plugin/package.json index 8f29b81dbce44dcf097b0cd658e669f273bfa3cc..a81d998eec0dad71f41a57332df947b3a75bf73b 100644 --- a/incremental/compiler-plugin/package.json +++ b/incremental/compiler-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/compiler-plugin", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "build/lib/src/index.js", "types": "build/lib/src/index.d.ts", @@ -10,7 +10,7 @@ ], "keywords": [], "dependencies": { - "@koalaui/common": "1.5.3+devel" + "@koalaui/common": "1.5.5+devel" }, "devDependencies": { "@types/chai": "^4.3.1", diff --git a/incremental/harness/package.json b/incremental/harness/package.json index 257c87491e6079340a52e18298ac30901322ecfe..399333031c979e4e1160bad4cf8b042c6c9b8644 100644 --- a/incremental/harness/package.json +++ b/incremental/harness/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/harness", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "A harness library compatible with OHOS and ArkTS", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -35,8 +35,8 @@ }, "keywords": [], "dependencies": { - "@koalaui/common": "1.5.3+devel", - "@koalaui/compat": "1.5.3+devel" + "@koalaui/common": "1.5.5+devel", + "@koalaui/compat": "1.5.5+devel" }, "devDependencies": { "@ohos/hypium": "1.0.6", diff --git a/incremental/runtime/package.json b/incremental/runtime/package.json index e20c6e8fd05ad09cc9d6ef73254148065755d41b..a0f66505624793327a3b08c1e8bb6ed948280a35 100644 --- a/incremental/runtime/package.json +++ b/incremental/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/runtime", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "main": "./build/lib/src/index.js", "types": "./build/lib/src/index.d.ts", @@ -41,9 +41,9 @@ }, "keywords": [], "dependencies": { - "@koalaui/common": "1.5.3+devel", - "@koalaui/compat": "1.5.3+devel", - "@koalaui/harness": "1.5.3+devel" + "@koalaui/common": "1.5.5+devel", + "@koalaui/compat": "1.5.5+devel", + "@koalaui/harness": "1.5.5+devel" }, "devDependencies": { "@types/chai": "^4.3.1", diff --git a/interop/package.json b/interop/package.json index 511ad48a36547acc1d7f44faf013bc175635bef1..7f0af0df812fac5630f90641754300139049db37 100644 --- a/interop/package.json +++ b/interop/package.json @@ -1,6 +1,6 @@ { "name": "@koalaui/interop", - "version": "1.5.3+devel", + "version": "1.5.5+devel", "description": "", "workspaces": [ "../incremental/build-common", @@ -57,7 +57,7 @@ "keywords": [], "dependencies": { "@types/node": "^18.0.0", - "@koalaui/common": "1.5.3+devel" + "@koalaui/common": "1.5.5+devel" }, "devDependencies": { "@ohos/hypium": "1.0.6", diff --git a/interop/src/cpp/ani/convertors-ani.h b/interop/src/cpp/ani/convertors-ani.h index 6ca8e43d990c62afc5b239db7ec577c4c4216754..c6aaaf46c992f103244d96a99a32a44e05453895 100644 --- a/interop/src/cpp/ani/convertors-ani.h +++ b/interop/src/cpp/ani/convertors-ani.h @@ -1367,11 +1367,11 @@ void getKoalaEtsNapiCallbackDispatcher(ani_class* clazz, ani_method* method); #else #define KOALA_INTEROP_CALL_VOID(venv, id, length, args) -#define KOALA_INTEROP_CALL_INT(venv, id, length, args) -#define KOALA_INTEROP_CALL_VOID_INTS32(venv, id, argc, args) -#define KOALA_INTEROP_CALL_INT_INTS32(venv, id, argc, args) -#define KOALA_INTEROP_THROW(vmContext, object, ...) -#define KOALA_INTEROP_THROW_STRING(vmContext, message, ...) +#define KOALA_INTEROP_CALL_INT(venv, id, length, args) { return 0; } +#define KOALA_INTEROP_CALL_VOID_INTS32(venv, id, argc, args) { return; } +#define KOALA_INTEROP_CALL_INT_INTS32(venv, id, argc, args) { return 0; } +#define KOALA_INTEROP_THROW(vmContext, object, ...) { return __VA_ARGS__; } +#define KOALA_INTEROP_THROW_STRING(vmContext, message, ...) { return __VA_ARGS__; } #endif #endif // KOALA_ETS_NAPI diff --git a/interop/src/cpp/common-interop.cc b/interop/src/cpp/common-interop.cc index c522cc84ab0bd84559822dbc4005e071c0c42f42..f7f5b74a6196f0e029b4b70a37b20ae0d8580e51 100644 --- a/interop/src/cpp/common-interop.cc +++ b/interop/src/cpp/common-interop.cc @@ -259,7 +259,7 @@ struct ForeignVMContext { typedef KInt (*LoadVirtualMachine_t)(KInt vmKind, const char* classPath, const char* libraryPath, const struct ForeignVMContext* foreignVM); typedef KNativePointer (*StartApplication_t)(const char* appUrl, const char* appParams); typedef KBoolean (*RunApplication_t)(const KInt arg0, const KInt arg1); -typedef void (*EmitEvent_t)(const KInt type, const KInt target, const KInt arg0, const KInt arg1); +typedef const char* (*EmitEvent_t)(const KInt type, const KInt target, const KInt arg0, const KInt arg1); typedef void (*RestartWith_t)(const char* page); void* getImpl(const char* path, const char* name) { @@ -310,12 +310,15 @@ KBoolean impl_RunApplication(const KInt arg0, const KInt arg1) { } KOALA_INTEROP_2(RunApplication, KBoolean, KInt, KInt) -void impl_EmitEvent(const KInt type, const KInt target, const KInt arg0, const KInt arg1) { +KStringPtr impl_EmitEvent(KVMContext vmContext, KInt type, KInt target, KInt arg0, KInt arg1) { static EmitEvent_t impl = nullptr; if (!impl) impl = reinterpret_cast(getImpl(nullptr, "EmitEvent")); - impl(type, target, arg0, arg1); + const char* out = impl(type, target, arg0, arg1); + auto size = std::string(out).size(); + KStringPtr result(out, size, true); + return result; } -KOALA_INTEROP_V4(EmitEvent, KInt, KInt, KInt, KInt) +KOALA_INTEROP_CTX_4(EmitEvent, KStringPtr, KInt, KInt, KInt, KInt) void impl_RestartWith(const KStringPtr& page) { static RestartWith_t impl = nullptr; diff --git a/interop/src/cpp/vmloader.cc b/interop/src/cpp/vmloader.cc index d409a87809cda49b24ca74dfb50627c35307f5f4..e7eda0d423f7ca522c28c57f70d23030254936fd 100644 --- a/interop/src/cpp/vmloader.cc +++ b/interop/src/cpp/vmloader.cc @@ -310,7 +310,7 @@ const AppInfo javaAppInfo = { "enter", "(IIJ)Z", "emitEvent", - "(IIII)V", + "(IIII)Ljava/lang/String;", }; #endif @@ -324,7 +324,7 @@ const AppInfo pandaAppInfo = { "enter", "IIJ:Z", "emitEvent", - "IIII:V", + "IIII:Lstd/core/String;", }; const AppInfo harnessAppInfo = { "@koalaui/ets-harness/src/EtsHarnessApplication/EtsHarnessApplication", @@ -335,7 +335,7 @@ const AppInfo harnessAppInfo = { "enter", "II:Z", "emitEvent", - "IIII:V", + "IIII:Lstd/core/String;", "restartWith", "Lstd/core/String;:V" }; @@ -509,15 +509,15 @@ extern "C" DLL_EXPORT KBoolean RunApplication(const KInt arg0, const KInt arg1) return 1; } -extern "C" DLL_EXPORT void EmitEvent(const KInt type, const KInt target, const KInt arg0, const KInt arg1) { +extern "C" DLL_EXPORT const char* EmitEvent(const KInt type, const KInt target, const KInt arg0, const KInt arg1) { #ifdef KOALA_JNI if (g_vmEntry.vmKind == JAVA_VM_KIND) { JNIEnv* jEnv = (JNIEnv*)(g_vmEntry.env); if (!g_vmEntry.emitEvent) { LOGE("Cannot find emitEvent method"); - return; + return "-1"; } - jEnv->CallVoidMethod( + auto rv = (jstring)jEnv->CallObjectMethod( (jobject)(g_vmEntry.app), (jmethodID)(g_vmEntry.emitEvent), (jint)type, @@ -529,6 +529,8 @@ extern "C" DLL_EXPORT void EmitEvent(const KInt type, const KInt target, const K jEnv->ExceptionDescribe(); jEnv->ExceptionClear(); } + const char *result = jEnv->GetStringUTFChars(rv, 0); + return result; } #endif #ifdef KOALA_ETS_NAPI @@ -536,9 +538,9 @@ extern "C" DLL_EXPORT void EmitEvent(const KInt type, const KInt target, const K EtsEnv* etsEnv = (EtsEnv*)(g_vmEntry.env); if (!g_vmEntry.emitEvent) { LOGE("Cannot find emitEvent method"); - return; + return "-1"; } - etsEnv->CallVoidMethod( + auto rv = (ets_string)etsEnv->CallObjectMethod( (ets_object)(g_vmEntry.app), (ets_method)(g_vmEntry.emitEvent), (ets_int)type, @@ -551,8 +553,11 @@ extern "C" DLL_EXPORT void EmitEvent(const KInt type, const KInt target, const K etsEnv->ErrorDescribe(); etsEnv->ErrorClear(); } + const char *result = etsEnv->GetStringUTFChars(rv, 0); + return result; } #endif + return "-1"; } extern "C" DLL_EXPORT void RestartWith(const char* page) {