diff --git a/compiler/main.js b/compiler/main.js index d9de016..c6aab9d 100644 --- a/compiler/main.js +++ b/compiler/main.js @@ -380,6 +380,9 @@ function loadModuleInfo(projectConfig, envArgs) { projectConfig.nodeModulesPath = buildJsonInfo.nodeModulesPath; } projectConfig.pandaMode = buildJsonInfo.pandaMode; + if (buildJsonInfo.compatibleSdkVersion >= 9) { + partialUpdateConfig.partialUpdateMode = true; + } } } @@ -430,6 +433,10 @@ const globalProgram = { watchProgram: null }; +const partialUpdateConfig = { + partialUpdateMode: false +}; + exports.globalProgram = globalProgram; exports.projectConfig = projectConfig; exports.loadEntryObj = loadEntryObj; @@ -443,3 +450,4 @@ exports.loadModuleInfo = loadModuleInfo; exports.systemModules = systemModules; exports.checkAppResourcePath = checkAppResourcePath; exports.addSDKBuildDependencies = addSDKBuildDependencies; +exports.partialUpdateConfig = partialUpdateConfig; \ No newline at end of file diff --git a/compiler/package.json b/compiler/package.json index 6bdb1e6..8f99725 100644 --- a/compiler/package.json +++ b/compiler/package.json @@ -13,7 +13,7 @@ "build": "npm run generateSyntaxParser && npm run generateDeclarations && ./node_modules/.bin/babel ./src --out-dir lib --extensions .ts && node uglify-source.js lib", "create": "node ./lib/create.js --env projectName", "compile": "webpack --config webpack.config.js --env buildMode=debug projectName", - "test": "npm run build && mocha -r mocha-context/register test/test.js", + "test": "npm run build && mocha -r mocha-context/register test/test.js && mocha -r mocha-context/register test/test.js --partialUpdate", "generateDeclarations": "node ./build_declarations_file.js ../../../interface/sdk-js/api/@internal/component/ets ./declarations ./lib", "generateSyntaxParser": "node build_parser.js ./syntax_parser/dist", "postinstall": "node npm-install.js" diff --git a/compiler/src/pre_define.ts b/compiler/src/pre_define.ts index 6dd695a..e7aa6ee 100644 --- a/compiler/src/pre_define.ts +++ b/compiler/src/pre_define.ts @@ -275,3 +275,53 @@ export const ES2ABC: string = 'es2abc'; export const GENERATE_ID = 'generateId'; export const _GENERATE_ID = '__generate__Id'; + +export const COMPONENT_CONSTRUCTOR_INITIAL_PARAMS: string = 'setInitiallyProvidedValue'; +export const COMPONENT_RERENDER_FUNCTION: string = 'rerender'; +export const COMPONENT_CONSTRUCTOR_PURGE_VARIABLE_DEP: string = 'purgeVariableDependenciesOnElmtId'; +export const MARKDEPENDENTELEMENTSDIRTY: string = 'markDependentElementsDirty'; +export const ABOUT_TO_BE_DELETE_FUNCTION_ID__: string = 'id__'; +export const RMELMTID: string = 'rmElmtId'; +export const PURGEDEPENDENCYONELMTID: string = 'purgeDependencyOnElmtId'; +export const SETPROPERTYUNCHANGED: string = 'SetPropertyUnchanged'; +export const ABOUTTOBEDELETEDINTERNAL: string = 'aboutToBeDeletedInternal'; +export const UPDATEDIRTYELEMENTS: string = 'updateDirtyElements'; +export const BASICDECORATORS: Set = new Set([COMPONENT_STATE_DECORATOR, COMPONENT_PROP_DECORATOR, + COMPONENT_LINK_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR]); +export const LINKS_DECORATORS: Set = new Set([COMPONENT_LINK_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR]); +export const ISINITIALRENDER: string = 'isInitialRender'; +export const ELMTID: string = 'elmtId'; +export const STARTGETACCESSRECORDINGFOR: string = 'StartGetAccessRecordingFor'; +export const STOPGETACCESSRECORDING: string = 'StopGetAccessRecording'; +export const VIEWSTACKPROCESSOR: string = 'ViewStackProcessor'; +export const OBSERVECOMPONENTCREATION: string = 'observeComponentCreation'; +export const ISLAZYCREATE: string = 'isLazyCreate'; +export const DEEPRENDERFUNCTION: string = 'deepRenderFunction'; +export const ITEMCREATION: string = 'itemCreation'; +export const OBSERVEDSHALLOWRENDER: string = 'observedShallowRender'; +export const OBSERVEDDEEPRENDER:string = 'observedDeepRender'; +export const ItemComponents: string[] = ['ListItem', 'GridItem']; +export const FOREACHITEMGENFUNCTION: string = 'forEachItemGenFunction'; +export const __LAZYFOREACHITEMGENFUNCTION: string = '__lazyForEachItemGenFunction'; +export const _ITEM: string = '_item'; +export const FOREACHITEMIDFUNC: string = 'forEachItemIdFunc'; +export const __LAZYFOREACHITEMIDFUNC: string = '__lazyForEachItemIdFunc'; +export const FOREACHUPDATEFUNCTION: string = 'forEachUpdateFunction'; +export const ALLOCATENEWELMETIDFORNEXTCOMPONENT: string = 'AllocateNewElmetIdForNextComponent'; +export const STATE_OBJECTLINK_DECORATORS: string[] = [COMPONENT_STATE_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR]; +export const COMPONENT_INITIAl_RENDER_FUNCTION: string = 'initialRender'; +export const GRID_COMPONENT: string = 'Grid'; +export const GRIDITEM_COMPONENT: string = 'GridItem'; +export const WILLUSEPROXY: string = 'willUseProxy'; +export const TABCONTENT_COMPONENT: string = 'TabContent'; +export const BASE_COMPONENT_NAME_PU: string = 'ViewPU'; +export const GLOBAL_THIS: string = 'globalThis'; +export const OBSERVED_PROPERTY_SIMPLE_PU: string = 'ObservedPropertySimplePU'; +export const OBSERVED_PROPERTY_OBJECT_PU: string = 'ObservedPropertyObjectPU'; +export const SYNCHED_PROPERTY_SIMPLE_ONE_WAY_PU: string = 'SynchedPropertySimpleOneWayPU'; +export const SYNCHED_PROPERTY_SIMPLE_TWO_WAY_PU: string = 'SynchedPropertySimpleTwoWayPU'; +export const SYNCHED_PROPERTY_OBJECT_TWO_WAY_PU: string = 'SynchedPropertyObjectTwoWayPU'; +export const SYNCHED_PROPERTY_NESED_OBJECT_PU: string = 'SynchedPropertyNesedObjectPU'; +export const OBSERVED_PROPERTY_ABSTRACT_PU:string = 'ObservedPropertyAbstractPU'; +export const COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU: string = '__localStorage'; +export const COMPONENT_CONSTRUCTOR_LOCALSTORAGE_TYPE_PU: string = 'LocalStorage'; diff --git a/compiler/src/process_component_build.ts b/compiler/src/process_component_build.ts index eea4651..d6901d6 100644 --- a/compiler/src/process_component_build.ts +++ b/compiler/src/process_component_build.ts @@ -61,7 +61,31 @@ import { $$, PROPERTIES_ADD_DOUBLE_DOLLAR, ATTRIBUTE_ID, - RESOURCE + RESOURCE, + ISINITIALRENDER, + ELMTID, + VIEWSTACKPROCESSOR, + STOPGETACCESSRECORDING, + STARTGETACCESSRECORDINGFOR, + OBSERVECOMPONENTCREATION, + ISLAZYCREATE, + DEEPRENDERFUNCTION, + ITEMCREATION, + OBSERVEDSHALLOWRENDER, + OBSERVEDDEEPRENDER, + ItemComponents, + FOREACHITEMGENFUNCTION, + __LAZYFOREACHITEMGENFUNCTION, + _ITEM, + FOREACHITEMIDFUNC, + __LAZYFOREACHITEMIDFUNC, + FOREACHUPDATEFUNCTION, + COMPONENT_INITIAl_RENDER_FUNCTION, + GRIDITEM_COMPONENT, + GRID_COMPONENT, + WILLUSEPROXY, + TABCONTENT_COMPONENT, + GLOBAL_THIS } from './pre_define'; import { INNER_COMPONENT_NAMES, @@ -92,7 +116,7 @@ import { componentInfo, createFunction } from './utils'; -import { projectConfig } from '../main'; +import { partialUpdateConfig, projectConfig } from '../main'; import { transformLog, contextGlobal } from './process_ui_syntax'; import { props } from './compile_info'; import { CUSTOM_COMPONENT } from '../lib/pre_define'; @@ -100,7 +124,12 @@ import { CUSTOM_COMPONENT } from '../lib/pre_define'; export function processComponentBuild(node: ts.MethodDeclaration, log: LogInfo[]): ts.MethodDeclaration { let newNode: ts.MethodDeclaration; - const renderNode: ts.Identifier = ts.factory.createIdentifier(COMPONENT_RENDER_FUNCTION); + let renderNode: ts.Identifier; + if (!partialUpdateConfig.partialUpdateMode) { + renderNode = ts.factory.createIdentifier(COMPONENT_RENDER_FUNCTION); + } else { + renderNode = ts.factory.createIdentifier(COMPONENT_INITIAl_RENDER_FUNCTION); + } if (node.body && node.body.statements && node.body.statements.length && validateRootNode(node, log)) { newNode = ts.factory.updateMethodDeclaration(node, node.decorators, node.modifiers, @@ -119,7 +148,7 @@ export function processComponentBlock(node: ts.Block, isLazy: boolean, log: LogI const newStatements: ts.Statement[] = []; processComponentChild(node, newStatements, log, {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isInnerBuilder, parent); - if (isLazy) { + if (isLazy && !partialUpdateConfig.partialUpdateMode) { newStatements.unshift(createRenderingInProgress(true)); } if (isTransition) { @@ -130,7 +159,7 @@ export function processComponentBlock(node: ts.Block, isLazy: boolean, log: LogI createFunction(ts.factory.createIdentifier(COMPONENT_TRANSITION_NAME), ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null))); } - if (isLazy) { + if (isLazy && !partialUpdateConfig.partialUpdateMode) { newStatements.push(createRenderingInProgress(false)); } return ts.factory.updateBlock(node, newStatements); @@ -254,7 +283,11 @@ export function processComponentChild(node: ts.Block | ts.SourceFile, newStateme break; case ComponentType.forEachComponent: parent = undefined; - processForEachComponent(item, newStatements, log, isInnerBuilder); + if (!partialUpdateConfig.partialUpdateMode) { + processForEachComponent(item, newStatements, log, isInnerBuilder); + } else { + processForEachComponentNew(item, newStatements, log); + } break; case ComponentType.customBuilderMethod: parent = undefined; @@ -374,38 +407,28 @@ function parseEtsComponentExpression(node: ts.ExpressionStatement): EtsComponent return { etsComponentNode: etsComponentNode, hasAttr: hasAttr }; } -function processInnerComponent(node: ts.ExpressionStatement, newStatements: ts.Statement[], +function processInnerComponent(node: ts.ExpressionStatement, innerCompStatements: ts.Statement[], log: LogInfo[], parent: string = undefined): void { + const newStatements: ts.Statement[] = []; const res: CreateResult = createComponent(node, COMPONENT_CREATE_FUNCTION); newStatements.push(res.newNode); const nameResult: NameResult = { name: null }; validateEtsComponentNode(node.expression as ts.EtsComponentExpression, nameResult); - if (projectConfig.isPreview && nameResult.name && !NO_DEBUG_LINE_COMPONENT.has(nameResult.name)) { - let posOfNode: ts.LineAndCharacter; - let curFileName: string; - let line: number = 1; - let col: number = 1; - if (newsupplement.isAcceleratePreview) { - posOfNode = sourceNode.getLineAndCharacterOfPosition(getRealNodePos(node)); - curFileName = newsupplement.fileName; - if (posOfNode.line === 0) { - col = newsupplement.column - 15; - } - line = newsupplement.line; - } else { - posOfNode = transformLog.sourceFile.getLineAndCharacterOfPosition(getRealNodePos(node)); - curFileName = transformLog.sourceFile.fileName.replace(/\.ts$/, ''); - } - const projectPath: string = projectConfig.projectPath; - const debugInfo: string = - `${path.relative(projectPath, curFileName).replace(/\\+/g, '/')}` + - `(${posOfNode.line + line}:${posOfNode.character + col})`; - const debugNode: ts.ExpressionStatement = ts.factory.createExpressionStatement( - createFunction(ts.factory.createIdentifier(nameResult.name), - ts.factory.createIdentifier(COMPONENT_DEBUGLINE_FUNCTION), - ts.factory.createNodeArray([ts.factory.createStringLiteral(debugInfo)]))); - newStatements.push(debugNode); + if (partialUpdateConfig.partialUpdateMode && ItemComponents.includes(nameResult.name)) { + processItemComponent(node, nameResult, innerCompStatements, log); + } else if (partialUpdateConfig.partialUpdateMode && TABCONTENT_COMPONENT.includes(nameResult.name)) { + processTabContent(node, innerCompStatements, log); + } else { + processNormalComponent(node, nameResult, innerCompStatements, log, parent); } +} + +function processNormalComponent(node: ts.ExpressionStatement, nameResult: NameResult, + innerCompStatements: ts.Statement[], log: LogInfo[], parent: string = undefined): void { + const newStatements: ts.Statement[] = []; + const res: CreateResult = createComponent(node, COMPONENT_CREATE_FUNCTION); + newStatements.push(res.newNode); + processDebug(node, nameResult, newStatements); const etsComponentResult: EtsComponentResult = parseEtsComponentExpression(node); if (PROPERTIES_ADD_DOUBLE_DOLLAR.has(res.identifierNode.getText()) && etsComponentResult.etsComponentNode.arguments && etsComponentResult.etsComponentNode.arguments.length) { @@ -424,16 +447,426 @@ function processInnerComponent(node: ts.ExpressionStatement, newStatements: ts.S if (etsComponentResult.hasAttr) { bindComponentAttr(node, res.identifierNode, newStatements, log); } - processComponentChild(etsComponentResult.etsComponentNode.body, newStatements, log, + processInnerCompStatements(innerCompStatements, newStatements, node); + processComponentChild(etsComponentResult.etsComponentNode.body, innerCompStatements, log, {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, false, parent); } else { bindComponentAttr(node, res.identifierNode, newStatements, log); + processInnerCompStatements(innerCompStatements, newStatements, node); } if (res.isContainerComponent || res.needPop) { - newStatements.push(createComponent(node, COMPONENT_POP_FUNCTION).newNode); + innerCompStatements.push(createComponent(node, COMPONENT_POP_FUNCTION).newNode); } } +function processDebug(node: ts.Statement, nameResult: NameResult, newStatements: ts.Statement[]): void { + if (projectConfig.isPreview && nameResult.name && !NO_DEBUG_LINE_COMPONENT.has(nameResult.name)) { + let posOfNode: ts.LineAndCharacter; + let curFileName: string; + let line: number = 1; + let col: number = 1; + if (newsupplement.isAcceleratePreview) { + posOfNode = sourceNode.getLineAndCharacterOfPosition(getRealNodePos(node)); + curFileName = newsupplement.fileName; + if (posOfNode.line === 0) { + col = newsupplement.column - 15; + } + line = newsupplement.line; + } else { + posOfNode = transformLog.sourceFile.getLineAndCharacterOfPosition(getRealNodePos(node)); + curFileName = transformLog.sourceFile.fileName.replace(/\.ts$/, ''); + } + const projectPath: string = projectConfig.projectPath; + const debugInfo: string = `${path.relative(projectPath, curFileName).replace(/\\+/g, '/')}` + + `(${posOfNode.line + line}:${posOfNode.character + col})`; + const debugNode: ts.ExpressionStatement = ts.factory.createExpressionStatement( + createFunction(ts.factory.createIdentifier(nameResult.name), + ts.factory.createIdentifier(COMPONENT_DEBUGLINE_FUNCTION), + ts.factory.createNodeArray([ts.factory.createStringLiteral(debugInfo)]))); + newStatements.push(debugNode); + } +} + +function processInnerCompStatements( + innerCompStatements: ts.Statement[], + newStatements: ts.Statement[], + node: ts.Statement +): void { + if (!partialUpdateConfig.partialUpdateMode) { + innerCompStatements.push(...newStatements); + } else { + innerCompStatements.push(createComponentCreationStatement(node, newStatements)); + } +} + +function createComponentCreationStatement(node: ts.Statement, innerStatements: ts.Statement[]): ts.Statement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(OBSERVECOMPONENTCREATION) + ), undefined, + [ts.factory.createArrowFunction(undefined, undefined, + [ + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ELMTID), undefined, undefined, undefined), + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ISINITIALRENDER), undefined, undefined, undefined) + ], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ + createViewStackProcessorStatement(STARTGETACCESSRECORDINGFOR, ELMTID), + ...innerStatements, + createInitRenderStatement(node), + createViewStackProcessorStatement(STOPGETACCESSRECORDING) + ], + true + ) + )] + ) + ); +} + +function createViewStackProcessorStatement(propertyAccessName: string, elmtId?: string): ts.Statement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(VIEWSTACKPROCESSOR), + ts.factory.createIdentifier(propertyAccessName) + ), + undefined, + elmtId ? [ts.factory.createIdentifier(ELMTID)] : [] + ) + ); +} + +function createInitRenderStatement(node: ts.Statement): ts.Statement { + return ts.factory.createIfStatement( + ts.factory.createPrefixUnaryExpression( + ts.SyntaxKind.ExclamationToken, + ts.factory.createIdentifier(ISINITIALRENDER) + ), + ts.factory.createBlock( + [ + ts.isExpressionStatement(node) ? + createComponent(node, COMPONENT_POP_FUNCTION).newNode : createIfPop() + ], + true + ) + ); +} + +function processItemComponent(node: ts.ExpressionStatement, nameResult: NameResult, innerCompStatements: ts.Statement[], + log: LogInfo[]): void { + const itemRenderInnerStatements: ts.Statement[] = []; + const deepItemRenderInnerStatements: ts.Statement[] = []; + const res: CreateResult = createComponent(node, COMPONENT_CREATE_FUNCTION); + const itemCreateStatement: ts.Statement = createItemCreate(nameResult); + itemRenderInnerStatements.push(itemCreateStatement); + processDebug(node, nameResult, innerCompStatements); + const etsComponentResult: EtsComponentResult = parseEtsComponentExpression(node); + if (etsComponentResult.etsComponentNode.body && ts.isBlock(etsComponentResult.etsComponentNode.body)) { + if (etsComponentResult.hasAttr) { + bindComponentAttr(node, res.identifierNode, itemRenderInnerStatements, log); + } + processComponentChild(etsComponentResult.etsComponentNode.body, deepItemRenderInnerStatements, log); + } else { + bindComponentAttr(node, res.identifierNode, itemRenderInnerStatements, log); + } + innerCompStatements.push(createItemBlock(node, itemRenderInnerStatements, deepItemRenderInnerStatements)); +} + +function createItemCreate(nameResult: NameResult): ts.Statement { + return ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(nameResult.name), + ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), undefined, + [ts.factory.createIdentifier(DEEPRENDERFUNCTION), ts.factory.createIdentifier(ISLAZYCREATE)])); +} + +function createItemBlock( + node: ts.ExpressionStatement, + itemRenderInnerStatements: ts.Statement[], + deepItemRenderInnerStatements: ts.Statement[] +): ts.Block { + return ts.factory.createBlock( + [ + createIsLazyCreate(node), + createItemCreation(node, itemRenderInnerStatements), + createObservedShallowRender(node, itemRenderInnerStatements), + createObservedDeepRender(node, deepItemRenderInnerStatements), + createDeepRenderFunction(node, deepItemRenderInnerStatements), + ts.factory.createIfStatement( + ts.factory.createIdentifier(ISLAZYCREATE), + ts.factory.createBlock( + [ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createIdentifier(OBSERVEDSHALLOWRENDER), undefined, []))], true), + ts.factory.createBlock( + [ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createIdentifier(OBSERVEDDEEPRENDER), undefined, []))], true) + ) + ], + true + ); +} + +function createIsLazyCreate(node: ts.ExpressionStatement): ts.VariableStatement { + const etsComponent: ts.EtsComponentExpression = getEtsComponentExpression(node); + if (etsComponent) { + if ((etsComponent.expression as ts.Identifier).escapedText.toString() === GRIDITEM_COMPONENT) { + if (etsComponent.arguments[0] && (etsComponent.arguments[0] as ts.StringLiteral).text === 'false') { + return createIsLazyWithValue(false); + } else if (isLazyForEachChild(node)) { + return ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(ISLAZYCREATE), undefined, undefined, + ts.factory.createBinaryExpression(ts.factory.createBinaryExpression( + ts.factory.createParenthesizedExpression(ts.factory.createBinaryExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(GLOBAL_THIS), + ts.factory.createIdentifier(__LAZYFOREACHITEMGENFUNCTION)), ts.factory.createToken( + ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier(COMPONENT_IF_UNDEFINED))), + ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), ts.factory.createTrue()), + ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), + ts.factory.createParenthesizedExpression(ts.factory.createBinaryExpression( + ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(GRID_COMPONENT), ts.factory.createIdentifier(WILLUSEPROXY)), + undefined, []), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), + ts.factory.createTrue()))))],ts.NodeFlags.Const)); + } else { + return ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(ISLAZYCREATE), undefined, undefined, + ts.factory.createBinaryExpression( + ts.factory.createTrue(), ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), + ts.factory.createParenthesizedExpression(ts.factory.createBinaryExpression( + ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(GRID_COMPONENT), ts.factory.createIdentifier(WILLUSEPROXY) + ), undefined, []), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), + ts.factory.createTrue()))))], ts.NodeFlags.Const)); + } + } else { + if (etsComponent.arguments[0] && (etsComponent.arguments[0] as ts.StringLiteral).text === 'false') { + return createIsLazyWithValue(false); + } else if (isLazyForEachChild(node)) { + return ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(ISLAZYCREATE), undefined, undefined, + ts.factory.createBinaryExpression(ts.factory.createParenthesizedExpression( + ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier( + GLOBAL_THIS), ts.factory.createIdentifier(__LAZYFOREACHITEMGENFUNCTION)), ts.factory.createToken( + ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier(COMPONENT_IF_UNDEFINED))), + ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), ts.factory.createTrue()))], + ts.NodeFlags.Const)); + } else { + return createIsLazyWithValue(true); + } + } + } +} + +function createItemCreation( + node: ts.ExpressionStatement, + itemRenderInnerStatements: ts.Statement[] +): ts.VariableStatement { + return ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(ITEMCREATION), undefined, undefined, + ts.factory.createArrowFunction(undefined, undefined, + [ + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ELMTID), undefined, undefined, undefined), + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ISINITIALRENDER), undefined, undefined, undefined) + ], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ + createViewStackProcessorStatement(STARTGETACCESSRECORDINGFOR, ELMTID), + ...itemRenderInnerStatements, + ts.factory.createIfStatement( + ts.factory.createPrefixUnaryExpression( + ts.SyntaxKind.ExclamationToken, + ts.factory.createIdentifier(ISINITIALRENDER) + ), + ts.factory.createBlock( + [createComponent(node, COMPONENT_POP_FUNCTION).newNode], + true + ) + ), + createViewStackProcessorStatement(STOPGETACCESSRECORDING) + ], + true + ) + ) + )], + ts.NodeFlags.Const + ) + ); +} + +function createDeepRenderFunction( + node: ts.ExpressionStatement, + deepItemRenderInnerStatements: ts.Statement[] +): ts.VariableStatement { + return ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(DEEPRENDERFUNCTION), undefined, undefined, + ts.factory.createArrowFunction(undefined, undefined, + [ + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ELMTID), undefined, undefined, undefined), + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ISINITIALRENDER), undefined, undefined, undefined) + ], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ + ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createIdentifier(ITEMCREATION), undefined, + [ + ts.factory.createIdentifier(ELMTID), + ts.factory.createIdentifier(ISINITIALRENDER) + ] + )), + ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier('updateFuncByElmtId') + ), + ts.factory.createIdentifier('set') + ), undefined, + [ts.factory.createIdentifier(ELMTID), ts.factory.createIdentifier(ITEMCREATION)] + )), + ...deepItemRenderInnerStatements, + createComponent(node, COMPONENT_POP_FUNCTION).newNode + ], + true + ) + ) + )], + ts.NodeFlags.Const + ) + ); +} + +function createObservedShallowRender( + node: ts.ExpressionStatement, + itemRenderInnerStatements: ts.Statement[] +): ts.VariableStatement { + return ts.factory.createVariableStatement(undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(OBSERVEDSHALLOWRENDER), undefined, undefined, + ts.factory.createArrowFunction(undefined, undefined, [], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ + ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(OBSERVECOMPONENTCREATION) + ), undefined, + [ts.factory.createArrowFunction(undefined, undefined, + [ + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ELMTID), undefined, undefined, undefined), + ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(ISINITIALRENDER), undefined, undefined, undefined) + ], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [createViewStackProcessorStatement(STARTGETACCESSRECORDINGFOR, ELMTID), + itemRenderInnerStatements[0], + ts.factory.createIfStatement( + ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, + ts.factory.createIdentifier(ISINITIALRENDER)), + ts.factory.createBlock( + [createComponent(node, COMPONENT_POP_FUNCTION).newNode], true)), + createViewStackProcessorStatement(STOPGETACCESSRECORDING)], true + ) + )] + )), + createComponent(node, COMPONENT_POP_FUNCTION).newNode + ], + true + ) + ) + )], + ts.NodeFlags.Const + ) + ); +} + +function createObservedDeepRender( + node: ts.ExpressionStatement, + deepItemRenderInnerStatements: ts.Statement[] +): ts.VariableStatement { + return ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(OBSERVEDDEEPRENDER), + undefined, + undefined, + ts.factory.createArrowFunction( + undefined, + undefined, + [], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ + ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(OBSERVECOMPONENTCREATION) + ), + undefined, + [ts.factory.createIdentifier(ITEMCREATION)] + )), + ...deepItemRenderInnerStatements, + createComponent(node, COMPONENT_POP_FUNCTION).newNode + ], + true + ) + ) + )], + ts.NodeFlags.Const + ) + ); +} + +function processTabContent(node: ts.ExpressionStatement, innerCompStatements: ts.Statement[], log: LogInfo[]): void { + const TabContentComp: ts.EtsComponentExpression = getEtsComponentExpression(node); + const TabContentBody: ts.Block = TabContentComp.body; + let tabContentCreation: ts.Statement; + const tabContentPop: ts.Statement = ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(TABCONTENT_COMPONENT), + ts.factory.createIdentifier(COMPONENT_POP_FUNCTION)), undefined, [])); + const tabAttrs: ts.Statement[] = []; + if (TabContentBody && TabContentBody.statements.length) { + const newTabContentChildren: ts.Statement[] = []; + processComponentChild(TabContentBody, newTabContentChildren, log); + tabContentCreation = ts.factory.createExpressionStatement( + ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(TABCONTENT_COMPONENT), ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), + undefined, [ts.factory.createArrowFunction(undefined, undefined, [], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock([...newTabContentChildren], true))])); + bindComponentAttr(node, ts.factory.createIdentifier(TABCONTENT_COMPONENT), tabAttrs, log); + processInnerCompStatements(innerCompStatements, [tabContentCreation, ...tabAttrs], node); + } else { + tabContentCreation = ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(TABCONTENT_COMPONENT), + ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), undefined, [])); + bindComponentAttr(node, ts.factory.createIdentifier(TABCONTENT_COMPONENT), tabAttrs, log); + processInnerCompStatements(innerCompStatements, [tabContentCreation, ...tabAttrs], node); + } + innerCompStatements.push(tabContentPop); +} + function getRealNodePos(node: ts.Node): number { // @ts-ignore if (node.pos === -1 && node.expression) { @@ -463,7 +896,8 @@ function processForEachComponent(node: ts.ExpressionStatement, newStatements: ts ts.factory.createIdentifier(FOREACH_GET_RAW_OBJECT)), undefined, [argumentsArray[0]]); } argumentsArray.splice(0, 1, arrayObserveredObject); - const newArrowNode: ts.ArrowFunction = processForEachBlock(node.expression, log, isInnerBuilder); + const newArrowNode: ts.ArrowFunction = + processForEachBlock(node.expression, log, isInnerBuilder) as ts.ArrowFunction; if (newArrowNode) { argumentsArray.splice(1, 1, newArrowNode); } @@ -473,6 +907,160 @@ function processForEachComponent(node: ts.ExpressionStatement, newStatements: ts newStatements.push(node, popNode); } +function processForEachComponentNew(node: ts.ExpressionStatement, newStatements: ts.Statement[], + log: LogInfo[]): void { + const newForEachStatements: ts.Statement[] = []; + const popNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(createFunction( + (node.expression as ts.CallExpression).expression as ts.Identifier, + ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null)); + if (ts.isCallExpression(node.expression)) { + const argumentsArray: ts.Expression[] = Array.from(node.expression.arguments); + const propertyNode: ts.ExpressionStatement = ts.factory.createExpressionStatement( + ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( + node.expression.expression as ts.Identifier, + ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), undefined, [])); + const newArrowNode: ts.NodeArray = + processForEachBlock(node.expression, log) as ts.NodeArray; + const itemGenFunctionStatement: ts.VariableStatement = createItemGenFunctionStatement(node.expression, + argumentsArray, newArrowNode); + const itemIdFuncStatement: ts.VariableStatement = createItemIdFuncStatement(node.expression, argumentsArray); + const updateFunctionStatement: ts.ExpressionStatement = createUpdateFunctionStatement(argumentsArray); + const lazyForEachStatement: ts.ExpressionStatement = createLazyForEachStatement(argumentsArray); + if (node.expression.expression.getText() === COMPONENT_FOREACH) { + if (argumentsArray[2]) { + newForEachStatements.push(propertyNode, itemGenFunctionStatement, itemIdFuncStatement, updateFunctionStatement); + } else { + newForEachStatements.push(propertyNode, itemGenFunctionStatement, updateFunctionStatement); + } + newStatements.push(createComponentCreationStatement(node, newForEachStatements), popNode); + } else { + if (argumentsArray[2]) { + newStatements.push(ts.factory.createBlock([itemGenFunctionStatement, itemIdFuncStatement, lazyForEachStatement, + popNode], true)); + } else { + newStatements.push(ts.factory.createBlock([itemGenFunctionStatement, lazyForEachStatement, popNode], true)); + } + } + } +} + +function createItemGenFunctionStatement( + node: ts.CallExpression, + argumentsArray: ts.Expression[], + newArrowNode: ts.NodeArray +): ts.VariableStatement { + if (argumentsArray[1] && ts.isArrowFunction(argumentsArray[1])) { + return ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(node.expression.getText() === COMPONENT_FOREACH ? + FOREACHITEMGENFUNCTION : __LAZYFOREACHITEMGENFUNCTION), + undefined, undefined, + ts.factory.createArrowFunction( + undefined, undefined, + [ts.factory.createParameterDeclaration( + undefined, undefined, undefined, ts.factory.createIdentifier(_ITEM))], + undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + [ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier( + argumentsArray[1].parameters[0] && argumentsArray[1].parameters[0].name.getText()), + undefined, + undefined, + ts.factory.createIdentifier(_ITEM) + )], + ts.NodeFlags.Const + ) + ), + ...newArrowNode + ], + true + ) + ) + ) + ], + ts.NodeFlags.Const + ) + ); + } +} + +function createItemIdFuncStatement( + node: ts.CallExpression, + argumentsArray: ts.Expression[] +): ts.VariableStatement { + if (argumentsArray[2] && ts.isArrowFunction(argumentsArray[2])) { + return ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(node.expression.getText() === COMPONENT_FOREACH ? + FOREACHITEMIDFUNC : __LAZYFOREACHITEMIDFUNC), undefined, undefined, + ts.factory.createArrowFunction( + undefined, undefined, + [ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier( + argumentsArray[2].parameters[0] ? argumentsArray[2].parameters[0].name.escapedText : '' + ) + )], undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createIdentifier(argumentsArray[2].body ? argumentsArray[2].body.getText() : '') + ) + )], + ts.NodeFlags.Const + ) + ); + } +} + +function createUpdateFunctionStatement(argumentsArray: ts.Expression[]): ts.ExpressionStatement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(FOREACHUPDATEFUNCTION) + ), + undefined, + addForEachIdFuncParameter(argumentsArray) + ) + ); +} + +function addForEachIdFuncParameter(argumentsArray: ts.Expression[]): ts.Identifier[] { + const addForEachIdFuncParameterArr: ts.Identifier[] = []; + addForEachIdFuncParameterArr.push( + ts.factory.createIdentifier(ELMTID), + ts.factory.createIdentifier(argumentsArray[0] && argumentsArray[0].getText()) + ); + addForEachIdFuncParameterArr.push(ts.factory.createIdentifier(FOREACHITEMGENFUNCTION)); + if (argumentsArray[2]) { + addForEachIdFuncParameterArr.push(ts.factory.createIdentifier(FOREACHITEMIDFUNC)); + } + return addForEachIdFuncParameterArr; +} + +function createLazyForEachStatement(argumentsArray: ts.Expression[]): ts.ExpressionStatement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(COMPONENT_LAZYFOREACH), + ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION) + ), + undefined, + [ts.factory.createStringLiteral(componentInfo.id.toString()), + ts.factory.createThis(), + argumentsArray[0], + ts.factory.createIdentifier(__LAZYFOREACHITEMGENFUNCTION), + ts.factory.createIdentifier(__LAZYFOREACHITEMIDFUNC) + ] + ) + ); +} + function addForEachId(node: ts.ExpressionStatement): ts.ExpressionStatement { const forEachComponent: ts.CallExpression = node.expression as ts.CallExpression; return ts.factory.updateExpressionStatement(node, ts.factory.updateCallExpression( @@ -482,7 +1070,7 @@ function addForEachId(node: ts.ExpressionStatement): ts.ExpressionStatement { } function processForEachBlock(node: ts.CallExpression, log: LogInfo[], - isInnerBuilder: boolean = false): ts.ArrowFunction { + isInnerBuilder: boolean = false): ts.NodeArray | ts.ArrowFunction { if (node.arguments.length > 1 && ts.isArrowFunction(node.arguments[1])) { const isLazy: boolean = node.expression.getText() === COMPONENT_LAZYFOREACH; const arrowNode: ts.ArrowFunction = node.arguments[1] as ts.ArrowFunction; @@ -498,14 +1086,22 @@ function processForEachBlock(node: ts.CallExpression, log: LogInfo[], const blockNode: ts.Block = ts.factory.createBlock([statement], true); // @ts-ignore statement.parent = blockNode; - return ts.factory.updateArrowFunction( - arrowNode, arrowNode.modifiers, arrowNode.typeParameters, arrowNode.parameters, - arrowNode.type, arrowNode.equalsGreaterThanToken, processComponentBlock(blockNode, isLazy, log)); + if (!partialUpdateConfig.partialUpdateMode) { + return ts.factory.updateArrowFunction( + arrowNode, arrowNode.modifiers, arrowNode.typeParameters, arrowNode.parameters, + arrowNode.type, arrowNode.equalsGreaterThanToken, processComponentBlock(blockNode, isLazy, log)); + } else { + return processComponentBlock(blockNode, isLazy, log).statements; + } } else { - return ts.factory.updateArrowFunction( - arrowNode, arrowNode.modifiers, arrowNode.typeParameters, arrowNode.parameters, - arrowNode.type, arrowNode.equalsGreaterThanToken, - processComponentBlock(body, isLazy, log, false, isInnerBuilder)); + if (!partialUpdateConfig.partialUpdateMode) { + return ts.factory.updateArrowFunction( + arrowNode, arrowNode.modifiers, arrowNode.typeParameters, arrowNode.parameters, + arrowNode.type, arrowNode.equalsGreaterThanToken, + processComponentBlock(body, isLazy, log, false, isInnerBuilder)); + } else { + return processComponentBlock(body, isLazy, log).statements; + } } } return null; @@ -527,7 +1123,11 @@ function processIfStatement(node: ts.IfStatement, newStatements: ts.Statement[], const ifCreate: ts.ExpressionStatement = createIfCreate(); const newIfNode: ts.IfStatement = processInnerIfStatement(node, 0, log, isInnerBuilder); const ifPop: ts.ExpressionStatement = createIfPop(); - newStatements.push(ifCreate, newIfNode, ifPop); + if (!partialUpdateConfig.partialUpdateMode) { + newStatements.push(ifCreate, newIfNode, ifPop); + } else { + newStatements.push(createComponentCreationStatement(node, [ifCreate, newIfNode]), ifPop); + } } function processInnerIfStatement(node: ts.IfStatement, id: number, log: LogInfo[], @@ -1404,3 +2004,26 @@ function checkButtonParamHasLabel(node: ts.EtsComponentExpression, log: LogInfo[ } } } + +function isLazyForEachChild(node: ts.ExpressionStatement): boolean { + let temp: any = node.parent; + while(temp && !ts.isEtsComponentExpression(temp) && !ts.isCallExpression(temp)) { + temp = temp.parent; + } + if (temp && temp.expression && (temp.expression as ts.Identifier).escapedText.toString() === COMPONENT_LAZYFOREACH) { + return true; + } + return false; +} + +function createIsLazyWithValue(value: boolean): ts.VariableStatement { + if (value) { + return ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(ISLAZYCREATE), + undefined, undefined, ts.factory.createTrue())], ts.NodeFlags.Const)); + } else { + return ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(ISLAZYCREATE), + undefined, undefined, ts.factory.createFalse())], ts.NodeFlags.Const)); + } +} diff --git a/compiler/src/process_component_class.ts b/compiler/src/process_component_class.ts index 6cf0021..eef49ba 100644 --- a/compiler/src/process_component_class.ts +++ b/compiler/src/process_component_class.ts @@ -33,10 +33,13 @@ import { BASE_COMPONENT_NAME, CREATE_CONSTRUCTOR_PARAMS, COMPONENT_CONSTRUCTOR_UPDATE_PARAMS, + COMPONENT_CONSTRUCTOR_INITIAL_PARAMS, + COMPONENT_CONSTRUCTOR_PURGE_VARIABLE_DEP, COMPONENT_CONSTRUCTOR_DELETE_PARAMS, COMPONENT_DECORATOR_PREVIEW, CREATE_CONSTRUCTOR_SUBSCRIBER_MANAGER, ABOUT_TO_BE_DELETE_FUNCTION_ID, + ABOUT_TO_BE_DELETE_FUNCTION_ID__, CREATE_CONSTRUCTOR_GET_FUNCTION, CREATE_CONSTRUCTOR_DELETE_FUNCTION, FOREACH_OBSERVED_OBJECT, @@ -58,7 +61,19 @@ import { CUSTOM_COMPONENT, COMPONENT_CONSTRUCTOR_PARENT, COMPONENT_IF_UNDEFINED, - INNER_COMPONENT_MEMBER_DECORATORS + INNER_COMPONENT_MEMBER_DECORATORS, + COMPONENT_RERENDER_FUNCTION, + RMELMTID, + ABOUTTOBEDELETEDINTERNAL, + UPDATEDIRTYELEMENTS, + LINKS_DECORATORS, + BASE_COMPONENT_NAME_PU, + OBSERVED_PROPERTY_SIMPLE_PU, + OBSERVED_PROPERTY_OBJECT_PU, + SYNCHED_PROPERTY_SIMPLE_TWO_WAY_PU, + SYNCHED_PROPERTY_SIMPLE_ONE_WAY_PU, + SYNCHED_PROPERTY_NESED_OBJECT_PU, + OBSERVED_PROPERTY_ABSTRACT_PU } from './pre_define'; import { BUILDIN_STYLE_NAMES, @@ -72,7 +87,8 @@ import { componentCollection, linkCollection, localStorageLinkCollection, - localStoragePropCollection + localStoragePropCollection, + propCollection } from './validate_ui_syntax'; import { addConstructor, @@ -96,6 +112,7 @@ import { LogInfo, hasDecorator } from './utils'; +import { partialUpdateConfig } from '../main'; export function processComponentClass(node: ts.StructDeclaration, context: ts.TransformationContext, log: LogInfo[], program: ts.Program): ts.ClassDeclaration { @@ -130,6 +147,8 @@ function processMembers(members: ts.NodeArray, parentComponentN const newMembers: ts.ClassElement[] = []; const watchMap: Map = new Map(); const updateParamsStatements: ts.Statement[] = []; + const purgeVariableDepStatements: ts.Statement[] = []; + const rerenderStatements: ts.Statement[] = []; const deleteParamsStatements: ts.PropertyDeclaration[] = []; const checkController: ControllerType = { hasController: !componentCollection.customDialogs.has(parentComponentName.getText()) }; @@ -168,6 +187,7 @@ function processMembers(members: ts.NodeArray, parentComponentN if (result.getControllerSet()) { newMembers.push(result.getControllerSet()); } + processPropertyUnchanged(result, purgeVariableDepStatements, rerenderStatements); } } if (ts.isMethodDeclaration(item) && item.name) { @@ -182,7 +202,8 @@ function processMembers(members: ts.NodeArray, parentComponentN validateBuildMethodCount(buildCount, parentComponentName, log); validateHasController(parentComponentName, checkController, log); newMembers.unshift(addDeleteParamsFunc(deleteParamsStatements)); - newMembers.unshift(addUpdateParamsFunc(updateParamsStatements, parentComponentName)); + addIntoNewMembers(newMembers, parentComponentName, updateParamsStatements, + purgeVariableDepStatements, rerenderStatements); newMembers.unshift(addConstructor(ctorNode, watchMap, parentComponentName)); return newMembers; } @@ -202,6 +223,39 @@ function validateDecorators(item: ts.ClassElement, log: LogInfo[]): void { } } +function processPropertyUnchanged( + result: UpdateResult, + purgeVariableDepStatements: ts.Statement[], + rerenderStatements: ts.Statement[] +): void { + if (partialUpdateConfig.partialUpdateMode) { + if(result.getPurgeVariableDepStatement()) { + purgeVariableDepStatements.push(result.getPurgeVariableDepStatement()); + } + if(result.getRerenderStatement()) { + rerenderStatements.push(result.getRerenderStatement()); + } + } +} + +function addIntoNewMembers( + newMembers: ts.ClassElement[], + parentComponentName: ts.Identifier, + updateParamsStatements: ts.Statement[], + purgeVariableDepStatements: ts.Statement[], + rerenderStatements: ts.Statement[] +): void { + if (partialUpdateConfig.partialUpdateMode) { + newMembers.unshift( + addInitialParamsFunc(updateParamsStatements, parentComponentName), + addPurgeVariableDepFunc(purgeVariableDepStatements) + ); + newMembers.push(addRerenderFunc(rerenderStatements)); + } else { + newMembers.unshift(addUpdateParamsFunc(updateParamsStatements, parentComponentName)); + } +} + function addPropertyMember(item: ts.ClassElement, newMembers: ts.ClassElement[], program: ts.Program, parentComponentName: string, log: LogInfo[]): void { const propertyItem: ts.PropertyDeclaration = item as ts.PropertyDeclaration; @@ -216,38 +270,16 @@ function addPropertyMember(item: ts.ClassElement, newMembers: ts.ClassElement[], let newType: ts.TypeNode; decoratorName = propertyItem.decorators[i].getText().replace(/\(.*\)$/, '').trim(); let isLocalStorage: boolean = false; - switch (decoratorName) { - case COMPONENT_STATE_DECORATOR: - case COMPONENT_PROVIDE_DECORATOR: - newType = ts.factory.createTypeReferenceNode(isSimpleType(type, program, log) ? - OBSERVED_PROPERTY_SIMPLE : OBSERVED_PROPERTY_OBJECT, [type || - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]); - break; - case COMPONENT_LINK_DECORATOR: - case COMPONENT_CONSUME_DECORATOR: - newType = ts.factory.createTypeReferenceNode(isSimpleType(type, program, log) ? - SYNCHED_PROPERTY_SIMPLE_TWO_WAY : SYNCHED_PROPERTY_SIMPLE_ONE_WAY, [type || - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]); - break; - case COMPONENT_PROP_DECORATOR: - newType = ts.factory.createTypeReferenceNode(SYNCHED_PROPERTY_SIMPLE_ONE_WAY, [type || - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]); - break; - case COMPONENT_OBJECT_LINK_DECORATOR: - newType = ts.factory.createTypeReferenceNode(SYNCHED_PROPERTY_NESED_OBJECT, [type || - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]); - break; - case COMPONENT_STORAGE_PROP_DECORATOR: - case COMPONENT_STORAGE_LINK_DECORATOR: - newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT, [type || - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]); - break; - case COMPONENT_LOCAL_STORAGE_LINK_DECORATOR: - case COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: - newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT, [type || - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)]); - isLocalStorage = true; - break; + if (!partialUpdateConfig.partialUpdateMode) { + newType = createTypeReference(decoratorName, type, log, program); + } else { + newType = createTypeReferencePU(decoratorName, type, log, program); + } + if ( + decoratorName === COMPONENT_LOCAL_STORAGE_LINK_DECORATOR || + decoratorName === COMPONENT_LOCAL_STORAGE_PROP_DECORATOR + ) { + isLocalStorage = true; } updatePropertyItem = createPropertyDeclaration(propertyItem, newType, false, isLocalStorage, parentComponentName); @@ -430,10 +462,7 @@ function updateHeritageClauses(node: ts.StructDeclaration, log: LogInfo[]) }); } const result:ts.HeritageClause[] = []; - const heritageClause:ts.HeritageClause = ts.factory.createHeritageClause( - ts.SyntaxKind.ExtendsKeyword, - [ts.factory.createExpressionWithTypeArguments( - ts.factory.createIdentifier(BASE_COMPONENT_NAME), [])]); + const heritageClause:ts.HeritageClause = createHeritageClause(); result.push(heritageClause); return ts.factory.createNodeArray(result); } @@ -475,6 +504,7 @@ function judgmentParentType(node: ts.Node): boolean { export function createReference(node: ts.PropertyAssignment, log: LogInfo[]): ts.PropertyAssignment { const linkParentComponent: string[] = getParentNode(node, linkCollection).slice(1); + const propParentComponent: string[] = getParentNode(node, propCollection).slice(1); const propertyName: ts.Identifier = node.name as ts.Identifier; let initText: string; const LINK_REG: RegExp = /^\$/g; @@ -492,6 +522,9 @@ export function createReference(node: ts.PropertyAssignment, log: LogInfo[]): ts pos: initExpression.getStart() }); } + } else if (partialUpdateConfig.partialUpdateMode && isMatchInitExpression(initExpression) && + propParentComponent.includes(propertyName.escapedText.toString())) { + initText = initExpression.name.escapedText.toString(); } if (initText) { node = addDoubleUnderline(node, propertyName, initText); @@ -539,15 +572,29 @@ function addUpdateParamsFunc(statements: ts.Statement[], parentComponentName: ts return createParamsInitBlock(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS, statements, parentComponentName); } +function addInitialParamsFunc(statements: ts.Statement[], parentComponentName: ts.Identifier): ts.MethodDeclaration { + return createParamsInitBlock(COMPONENT_CONSTRUCTOR_INITIAL_PARAMS, statements, parentComponentName); +} + +function addPurgeVariableDepFunc(statements: ts.Statement[]): ts.MethodDeclaration { + return ts.factory.createMethodDeclaration( + undefined, undefined, undefined, + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PURGE_VARIABLE_DEP), + undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(RMELMTID), undefined, undefined, undefined)], undefined, + ts.factory.createBlock(statements, true)); +} + function addDeleteParamsFunc(statements: ts.PropertyDeclaration[]): ts.MethodDeclaration { const deleteStatements: ts.ExpressionStatement[] = []; statements.forEach((statement: ts.PropertyDeclaration) => { const name: ts.Identifier = statement.name as ts.Identifier; - const paramsStatement: ts.ExpressionStatement = ts.factory.createExpressionStatement( - ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createThis(), - ts.factory.createIdentifier(`__${name.escapedText.toString()}`)), - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_DELETE_PARAMS)), undefined, [])); + let paramsStatement: ts.ExpressionStatement; + if (partialUpdateConfig.partialUpdateMode && !statement.decorators) { + paramsStatement = createParamsStatement(name); + } else { + paramsStatement = createParamsWithUnderlineStatement(name); + } deleteStatements.push(paramsStatement); }); const defaultStatement: ts.ExpressionStatement = @@ -558,14 +605,55 @@ function addDeleteParamsFunc(statements: ts.PropertyDeclaration[]): ts.MethodDec ts.factory.createIdentifier(CREATE_CONSTRUCTOR_GET_FUNCTION)), undefined, []), ts.factory.createIdentifier(CREATE_CONSTRUCTOR_DELETE_FUNCTION)), undefined, [ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( - ts.factory.createThis(), ts.factory.createIdentifier(ABOUT_TO_BE_DELETE_FUNCTION_ID)), + ts.factory.createThis(), ts.factory.createIdentifier( + !partialUpdateConfig.partialUpdateMode ? + ABOUT_TO_BE_DELETE_FUNCTION_ID : ABOUT_TO_BE_DELETE_FUNCTION_ID__)), undefined, [])])); deleteStatements.push(defaultStatement); + if (partialUpdateConfig.partialUpdateMode) { + const aboutToBeDeletedInternalStatement: ts.ExpressionStatement = createDeletedInternalStatement(); + deleteStatements.push(aboutToBeDeletedInternalStatement); + } const deleteParamsMethod: ts.MethodDeclaration = createParamsInitBlock(COMPONENT_CONSTRUCTOR_DELETE_PARAMS, deleteStatements); return deleteParamsMethod; } +function createParamsStatement(name: ts.Identifier): ts.ExpressionStatement { + return ts.factory.createExpressionStatement(ts.factory.createBinaryExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(`${name.escapedText.toString()}`) + ), + ts.factory.createToken(ts.SyntaxKind.EqualsToken), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED) + )); +} + +function createParamsWithUnderlineStatement(name: ts.Identifier): ts.ExpressionStatement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createThis(), + ts.factory.createIdentifier(`__${name.escapedText.toString()}`)), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_DELETE_PARAMS)), undefined, [])); +} + +function createDeletedInternalStatement(): ts.ExpressionStatement { + return ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createThis(), + ts.factory.createIdentifier(ABOUTTOBEDELETEDINTERNAL)), undefined, [])); +} + +function addRerenderFunc(statements: ts.Statement[]): ts.MethodDeclaration { + let updateDirtyElementStatement: ts.Statement = ts.factory.createExpressionStatement( + ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), ts.factory.createIdentifier(UPDATEDIRTYELEMENTS)), undefined, [])); + statements.push(updateDirtyElementStatement); + return ts.factory.createMethodDeclaration(undefined, undefined, undefined, + ts.factory.createIdentifier(COMPONENT_RERENDER_FUNCTION), undefined, undefined, [], undefined, + ts.factory.createBlock(statements, true)); +} + function createParamsInitBlock(express: string, statements: ts.Statement[], parentComponentName?: ts.Identifier): ts.MethodDeclaration { const methodDeclaration: ts.MethodDeclaration = ts.factory.createMethodDeclaration(undefined, @@ -601,3 +689,116 @@ function validateHasController(componentName: ts.Identifier, checkController: Co }); } } + +function createHeritageClause(): ts.HeritageClause { + if (partialUpdateConfig.partialUpdateMode) { + return ts.factory.createHeritageClause( + ts.SyntaxKind.ExtendsKeyword, + [ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier(BASE_COMPONENT_NAME_PU), [])] + ); + } + return ts.factory.createHeritageClause( + ts.SyntaxKind.ExtendsKeyword, + [ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier(BASE_COMPONENT_NAME), [])] + ); +} + +function createTypeReference(decoratorName: string, type: ts.TypeNode, log: LogInfo[], + program: ts.Program): ts.TypeNode { + let newType: ts.TypeNode; + switch (decoratorName) { + case COMPONENT_STATE_DECORATOR: + case COMPONENT_PROVIDE_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + isSimpleType(type, program, log) + ? OBSERVED_PROPERTY_SIMPLE + : OBSERVED_PROPERTY_OBJECT, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_LINK_DECORATOR: + case COMPONENT_CONSUME_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + isSimpleType(type, program, log) + ? SYNCHED_PROPERTY_SIMPLE_TWO_WAY + : SYNCHED_PROPERTY_SIMPLE_ONE_WAY, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_PROP_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + SYNCHED_PROPERTY_SIMPLE_ONE_WAY, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_OBJECT_LINK_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + SYNCHED_PROPERTY_NESED_OBJECT, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_STORAGE_PROP_DECORATOR: + case COMPONENT_STORAGE_LINK_DECORATOR: + newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT, [ + type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + ]); + break; + case COMPONENT_LOCAL_STORAGE_LINK_DECORATOR: + case COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: + newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT, [ + type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + ]); + break; + } + return newType; +} + +function createTypeReferencePU(decoratorName: string, type: ts.TypeNode, log: LogInfo[], + program: ts.Program): ts.TypeNode { + let newType: ts.TypeNode; + switch (decoratorName) { + case COMPONENT_STATE_DECORATOR: + case COMPONENT_PROVIDE_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + isSimpleType(type, program, log) + ? OBSERVED_PROPERTY_SIMPLE_PU + : OBSERVED_PROPERTY_OBJECT_PU, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_LINK_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + isSimpleType(type, program, log) + ? SYNCHED_PROPERTY_SIMPLE_TWO_WAY_PU + : SYNCHED_PROPERTY_SIMPLE_ONE_WAY_PU, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_PROP_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + SYNCHED_PROPERTY_SIMPLE_ONE_WAY_PU, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_OBJECT_LINK_DECORATOR: + newType = ts.factory.createTypeReferenceNode( + SYNCHED_PROPERTY_NESED_OBJECT_PU, + [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)] + ); + break; + case COMPONENT_CONSUME_DECORATOR: + case COMPONENT_STORAGE_PROP_DECORATOR: + case COMPONENT_STORAGE_LINK_DECORATOR: + newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT_PU, [ + type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + ]); + break; + case COMPONENT_LOCAL_STORAGE_LINK_DECORATOR: + case COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: + newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT_PU, [ + type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + ]); + break; + } + return newType; +} diff --git a/compiler/src/process_component_constructor.ts b/compiler/src/process_component_constructor.ts index 5b04845..27bcb78 100644 --- a/compiler/src/process_component_constructor.ts +++ b/compiler/src/process_component_constructor.ts @@ -20,10 +20,14 @@ import { COMPONENT_CONSTRUCTOR_PARENT, COMPONENT_CONSTRUCTOR_PARAMS, COMPONENT_CONSTRUCTOR_UPDATE_PARAMS, + COMPONENT_CONSTRUCTOR_INITIAL_PARAMS, COMPONENT_WATCH_FUNCTION, BASE_COMPONENT_NAME, INTERFACE_NAME_SUFFIX, - COMPONENT_CONSTRUCTOR_LOCALSTORAGE + COMPONENT_CONSTRUCTOR_LOCALSTORAGE, + BASE_COMPONENT_NAME_PU, + COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU, + COMPONENT_CONSTRUCTOR_LOCALSTORAGE_TYPE_PU } from './pre_define'; import { @@ -31,6 +35,8 @@ import { localStoragePropCollection } from './validate_ui_syntax'; +import { partialUpdateConfig } from '../main'; + export function getInitConstructor(members: ts.NodeArray, parentComponentName: ts.Identifier ): ts.ConstructorDeclaration { let ctorNode: any = members.find(item => { @@ -83,9 +89,16 @@ function initConstructorParams(node: ts.ConstructorDeclaration, parentComponentN } const localStorageNum: number = localStorageLinkCollection.get(parentComponentName.getText()).size + localStoragePropCollection.get(parentComponentName.getText()).size; - const paramNames: Set = new Set([COMPONENT_CONSTRUCTOR_ID, COMPONENT_CONSTRUCTOR_PARENT, - COMPONENT_CONSTRUCTOR_PARAMS, localStorageNum ? COMPONENT_CONSTRUCTOR_LOCALSTORAGE : - COMPONENT_CONSTRUCTOR_PARAMS]); + const paramNames: Set = !partialUpdateConfig.partialUpdateMode ? new Set([ + COMPONENT_CONSTRUCTOR_ID, + COMPONENT_CONSTRUCTOR_PARENT, + COMPONENT_CONSTRUCTOR_PARAMS, + localStorageNum ? COMPONENT_CONSTRUCTOR_LOCALSTORAGE : COMPONENT_CONSTRUCTOR_PARAMS + ]) : new Set([ + COMPONENT_CONSTRUCTOR_PARENT, + COMPONENT_CONSTRUCTOR_PARAMS, + COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU + ]); const newParameters: ts.ParameterDeclaration[] = Array.from(node.parameters); if (newParameters.length !== 0) { // @ts-ignore @@ -117,7 +130,8 @@ function addParamsType(ctorNode: ts.ConstructorDeclaration, modifyPara: ts.Param case COMPONENT_CONSTRUCTOR_PARENT: parameter = ts.factory.createParameterDeclaration(item.decorators, item.modifiers, item.dotDotDotToken, item.name, item.questionToken, - ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(BASE_COMPONENT_NAME), undefined), + ts.factory.createTypeReferenceNode(ts.factory.createIdentifier( + !partialUpdateConfig.partialUpdateMode ? BASE_COMPONENT_NAME : BASE_COMPONENT_NAME_PU), undefined), item.initializer); break; case COMPONENT_CONSTRUCTOR_PARAMS: @@ -126,6 +140,11 @@ function addParamsType(ctorNode: ts.ConstructorDeclaration, modifyPara: ts.Param ts.factory.createTypeReferenceNode(ts.factory.createIdentifier( parentComponentName.getText() + INTERFACE_NAME_SUFFIX), undefined), item.initializer); break; + case COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU: + parameter = ts.factory.createParameterDeclaration(item.decorators, item.modifiers, item.dotDotDotToken, + item.name, ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE_TYPE_PU), undefined), item.initializer); + break; } newTSPara.push(parameter); }); @@ -154,19 +173,41 @@ export function addConstructor(ctorNode: any, watchMap: Map, )); watchStatements.push(watchNode); }); - const callSuperStatement: ts.Statement = ts.factory.createExpressionStatement( - ts.factory.createCallExpression(ts.factory.createSuper(), undefined, - localStorageNum ? - [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID), - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE)] : - [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID), - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)] - )); - const updateWithValueParamsStatement: ts.Statement = ts.factory.createExpressionStatement( - ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( - ts.factory.createThis(), ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS)), - undefined, [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARAMS)])); + const callSuperStatement: ts.Statement = createCallSuperStatement(localStorageNum); + const updateWithValueParamsStatement: ts.Statement = createUPdWithValStatement(); return updateConstructor(updateConstructor(ctorNode, [], [callSuperStatement], true), [], [...watchStatements, updateWithValueParamsStatement], false, true, parentComponentName); } + +function createCallSuperStatement(localStorageNum: number): ts.Statement{ + if (!partialUpdateConfig.partialUpdateMode) { + return ts.factory.createExpressionStatement(ts.factory.createCallExpression( + ts.factory.createSuper(), undefined, + localStorageNum ? [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE)] : + [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)])); + } else { + return (ts.factory.createExpressionStatement( + ts.factory.createCallExpression(ts.factory.createSuper(), undefined, + [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU)]))); + } +} + +function createUPdWithValStatement(): ts.Statement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier( + !partialUpdateConfig.partialUpdateMode ? + COMPONENT_CONSTRUCTOR_UPDATE_PARAMS : COMPONENT_CONSTRUCTOR_INITIAL_PARAMS + ) + ), + undefined, + [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARAMS)] + ) + ); +} \ No newline at end of file diff --git a/compiler/src/process_component_member.ts b/compiler/src/process_component_member.ts index e1461c5..7923364 100644 --- a/compiler/src/process_component_member.ts +++ b/compiler/src/process_component_member.ts @@ -55,7 +55,19 @@ import { COMPONENT_LOCAL_STORAGE_PROP_DECORATOR, COMPONENT_CONSTRUCTOR_PARENT, EXTNAME_ETS, - _GENERATE_ID + _GENERATE_ID, + MARKDEPENDENTELEMENTSDIRTY, + RMELMTID, + PURGEDEPENDENCYONELMTID, + SETPROPERTYUNCHANGED, + BASICDECORATORS, + BASE_COMPONENT_NAME_PU, + OBSERVED_PROPERTY_SIMPLE_PU, + OBSERVED_PROPERTY_OBJECT_PU, + SYNCHED_PROPERTY_SIMPLE_TWO_WAY_PU, + SYNCHED_PROPERTY_OBJECT_TWO_WAY_PU, + SYNCHED_PROPERTY_SIMPLE_ONE_WAY_PU, + SYNCHED_PROPERTY_NESED_OBJECT_PU } from './pre_define'; import { forbiddenUseStateType, @@ -81,6 +93,8 @@ import { import { transformLog } from './process_ui_syntax'; import { globalProgram, projectConfig } from '../main'; +import { partialUpdateConfig } from '../main'; + export type ControllerType = { hasController: boolean } @@ -129,6 +143,9 @@ export class UpdateResult { private updateParams: ts.Statement; private deleteParams: boolean = false; private controllerSet: ts.MethodDeclaration; + private purgeVariableDepStatement: ts.Statement; + private rerenderStatement: ts.Statement; + private decoratorName: string; public setProperity(updateItem: ts.PropertyDeclaration) { this.itemUpdate = true; @@ -164,6 +181,18 @@ export class UpdateResult { this.deleteParams = deleteParams; } + public setPurgeVariableDepStatement(purgeVariableDepStatement: ts.Statement) { + this.purgeVariableDepStatement = purgeVariableDepStatement; + } + + public setRerenderStatement(rerenderStatement: ts.Statement) { + this.rerenderStatement = rerenderStatement; + } + + public setDecoratorName(decoratorName: string) { + this.decoratorName = decoratorName; + } + public isItemUpdate(): boolean { return this.itemUpdate; } @@ -184,6 +213,14 @@ export class UpdateResult { return this.updateParams; } + public getPurgeVariableDepStatement(): ts.Statement { + return this.purgeVariableDepStatement; + } + + public getRerenderStatement(): ts.Statement { + return this.rerenderStatement; + } + public getVariableGet(): ts.GetAccessorDeclaration { return this.variableGet; } @@ -192,6 +229,10 @@ export class UpdateResult { return this.variableSet; } + public getDecoratorName(): string { + return this.decoratorName; + } + public isDeleteParams(): boolean { return this.deleteParams; } @@ -213,6 +254,9 @@ export function processMemberVariableDecorators(parentName: ts.Identifier, createVariableInitStatement(item, COMPONENT_NON_DECORATOR, log, program, context, hasPreview, interfaceNode)])); updateResult.setControllerSet(createControllerSet(item, parentName, name, checkController)); + if (partialUpdateConfig.partialUpdateMode) { + updateResult.setDeleteParams(true); + } } else if (!item.type) { validatePropertyNonType(name, log); return updateResult; @@ -317,6 +361,44 @@ function processStateDecorators(node: ts.PropertyDeclaration, decorator: string, if (setUpdateParamsDecorators.has(decorator)) { updateResult.setUpdateParams(createUpdateParams(name, decorator)); } + if (partialUpdateConfig.partialUpdateMode && BASICDECORATORS.has(decorator)) { + const variableWithUnderLink: string = '__' + name.escapedText.toString(); + updateResult.setDecoratorName(decorator); + updateResult.setPurgeVariableDepStatement(createPurgeVariableDepStatement(variableWithUnderLink)); + updateResult.setRerenderStatement(createRerenderStatement(variableWithUnderLink)); + } +} + +function createPurgeVariableDepStatement(variableWithUnderLink: string): ts.Statement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(variableWithUnderLink) + ), + ts.factory.createIdentifier(PURGEDEPENDENCYONELMTID) + ), + undefined, + [ts.factory.createIdentifier(RMELMTID)] + ) + ); +} + +function createRerenderStatement(variableWithUnderLink: string): ts.Statement { + return ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(variableWithUnderLink) + ), + ts.factory.createIdentifier(MARKDEPENDENTELEMENTSDIRTY) + ), + undefined, + [ts.factory.createThis()] + ) + ); } function processWatch(node: ts.PropertyDeclaration, decorator: ts.Decorator, @@ -368,15 +450,19 @@ function createVariableInitStatement(node: ts.PropertyDeclaration, decorator: st break; case COMPONENT_STATE_DECORATOR: case COMPONENT_PROVIDE_DECORATOR: - updateState = updateObservedProperty(node, name, type, program); + updateState = !partialUpdateConfig.partialUpdateMode ? + updateObservedProperty(node, name, type, program) : updateObservedPropertyPU(node, name, type, program); break; case COMPONENT_LINK_DECORATOR: wrongDecoratorInPreview(node, COMPONENT_LINK_DECORATOR, hasPreview, log); - updateState = updateSynchedPropertyTwoWay(name, type, program); + updateState = !partialUpdateConfig.partialUpdateMode ? + updateSynchedPropertyTwoWay(name, type, program) : updateSynchedPropertyTwoWayPU(name, type, program); break; case COMPONENT_PROP_DECORATOR: wrongDecoratorInPreview(node, COMPONENT_PROP_DECORATOR, hasPreview, log); - updateState = updateSynchedPropertyOneWay(name, type, decorator, log, program); + updateState = !partialUpdateConfig.partialUpdateMode + ? updateSynchedPropertyOneWay(name, type, decorator, log, program) + : updateSynchedPropertyOneWayPU(name, type, decorator, log, program); break; case COMPONENT_STORAGE_PROP_DECORATOR: case COMPONENT_STORAGE_LINK_DECORATOR: @@ -385,7 +471,9 @@ function createVariableInitStatement(node: ts.PropertyDeclaration, decorator: st updateState = updateStoragePropAndLinkProperty(node, name, setFuncName, log); break; case COMPONENT_OBJECT_LINK_DECORATOR: - updateState = updateSynchedPropertyNesedObject(name, type, decorator, log); + updateState = !partialUpdateConfig.partialUpdateMode + ? updateSynchedPropertyNesedObject(name, type, decorator, log) + : updateSynchedPropertyNesedObjectPU(name, type, decorator, log); break; case COMPONENT_CONSUME_DECORATOR: wrongDecoratorInPreview(node, COMPONENT_CONSUME_DECORATOR, hasPreview, log); @@ -422,6 +510,10 @@ function createUpdateParams(name: ts.Identifier, decorator: string): ts.Statemen updateParamsNode = createUpdateParamsWithIf(name); break; case COMPONENT_PROP_DECORATOR: + if (!partialUpdateConfig.partialUpdateMode) { + updateParamsNode = createUpdateParamsWithoutIf(name); + } + break; case COMPONENT_BUILDERPARAM_DECORATOR: updateParamsNode = createUpdateParamsWithoutIf(name); break; @@ -570,6 +662,10 @@ function createCustomComponentBuilderArrowFunction(parent: ts.PropertyDeclaratio } export function createViewCreate(node: ts.NewExpression | ts.Identifier): ts.CallExpression { + if (partialUpdateConfig.partialUpdateMode) { + return createFunction(ts.factory.createIdentifier(BASE_COMPONENT_NAME_PU), + ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), ts.factory.createNodeArray([node])); + } return createFunction(ts.factory.createIdentifier(BASE_COMPONENT_NAME), ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), ts.factory.createNodeArray([node])); } @@ -595,17 +691,21 @@ function addCustomComponentId(node: ts.NewExpression, componentName: string, if (!argumentsArray) { argumentsArray = [ts.factory.createObjectLiteralExpression([], true)]; } - ++componentInfo.id; - argumentsArray.unshift(isInnerBuilder ? ts.factory.createBinaryExpression( - ts.factory.createStringLiteral(path.basename(transformLog.sourceFile.fileName, EXTNAME_ETS) + '_'), - ts.factory.createToken(ts.SyntaxKind.PlusToken), ts.factory.createIdentifier(_GENERATE_ID)) : - ts.factory.createStringLiteral(componentInfo.id.toString()), - isInnerBuilder ? ts.factory.createConditionalExpression( - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), - ts.factory.createToken(ts.SyntaxKind.QuestionToken), - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), - ts.factory.createToken(ts.SyntaxKind.ColonToken), ts.factory.createThis() - ) : ts.factory.createThis()); + if (!partialUpdateConfig.partialUpdateMode) { + ++componentInfo.id; + argumentsArray.unshift(isInnerBuilder ? ts.factory.createBinaryExpression( + ts.factory.createStringLiteral(path.basename(transformLog.sourceFile.fileName, EXTNAME_ETS) + '_'), + ts.factory.createToken(ts.SyntaxKind.PlusToken), ts.factory.createIdentifier(_GENERATE_ID)) : + ts.factory.createStringLiteral(componentInfo.id.toString()), + isInnerBuilder ? ts.factory.createConditionalExpression( + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createToken(ts.SyntaxKind.ColonToken), ts.factory.createThis() + ) : ts.factory.createThis()); + } else { + argumentsArray.unshift(ts.factory.createThis()); + } node = ts.factory.updateNewExpression(node, node.expression, node.typeArguments, argumentsArray); } else if (argumentsArray) { @@ -900,3 +1000,42 @@ function validateVariableType(typeNode: ts.TypeNode, log: LogInfo[]): void { }); } +function updateObservedPropertyPU(item: ts.PropertyDeclaration, name: ts.Identifier, + type: ts.TypeNode, program: ts.Program): ts.ExpressionStatement { + return ts.factory.createExpressionStatement(ts.factory.createBinaryExpression( + createPropertyAccessExpressionWithThis(`__${name.getText()}`), + ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createNewExpression( + ts.factory.createIdentifier(isSimpleType(type, program) ? OBSERVED_PROPERTY_SIMPLE_PU : + OBSERVED_PROPERTY_OBJECT_PU), undefined, [item.initializer, ts.factory.createThis(), + ts.factory.createStringLiteral(name.escapedText.toString())]))); +} + +function updateSynchedPropertyTwoWayPU(nameIdentifier: ts.Identifier, type: ts.TypeNode, + program: ts.Program): ts.ExpressionStatement { + const name: string = nameIdentifier.escapedText.toString(); + const functionName: string = isSimpleType(type, program) ? + SYNCHED_PROPERTY_SIMPLE_TWO_WAY_PU : SYNCHED_PROPERTY_OBJECT_TWO_WAY_PU; + return createInitExpressionStatementForDecorator(name, functionName, + createPropertyAccessExpressionWithParams(name)); +} + +function updateSynchedPropertyOneWayPU(nameIdentifier: ts.Identifier, type: ts.TypeNode, + decoractor: string, log: LogInfo[], program: ts.Program): ts.ExpressionStatement { + const name: string = nameIdentifier.escapedText.toString(); + if (isSimpleType(type, program)) { + return createInitExpressionStatementForDecorator(name, SYNCHED_PROPERTY_SIMPLE_ONE_WAY_PU, + createPropertyAccessExpressionWithParams(name)); + } else { + validateNonSimpleType(nameIdentifier, decoractor, log); + } +} + +function updateSynchedPropertyNesedObjectPU(nameIdentifier: ts.Identifier, + type: ts.TypeNode, decoractor: string, log: LogInfo[]): ts.ExpressionStatement { + if (isObservedClassType(type)) { + return createInitExpressionStatementForDecorator(nameIdentifier.getText(), SYNCHED_PROPERTY_NESED_OBJECT_PU, + createPropertyAccessExpressionWithParams(nameIdentifier.getText())); + } else { + validateNonObservedClassType(nameIdentifier, decoractor, log); + } +} diff --git a/compiler/src/process_custom_component.ts b/compiler/src/process_custom_component.ts index 6c69be9..6aff256 100644 --- a/compiler/src/process_custom_component.ts +++ b/compiler/src/process_custom_component.ts @@ -34,7 +34,14 @@ import { CUSTOM_COMPONENT_MARK_STATIC_FUNCTION, COMPONENT_COMMON, COMPONENT_CONSTRUCTOR_PARENT, - GENERATE_ID + GENERATE_ID, + ELMTID, + VIEWSTACKPROCESSOR, + STARTGETACCESSRECORDINGFOR, + STOPGETACCESSRECORDING, + ALLOCATENEWELMETIDFORNEXTCOMPONENT, + STATE_OBJECTLINK_DECORATORS, + BASE_COMPONENT_NAME_PU } from './pre_define'; import { propertyCollection, @@ -64,6 +71,7 @@ import { createFunction } from './utils'; import { bindComponentAttr } from './process_component_build'; +import { partialUpdateConfig } from '../main'; const localArray: string[] = [...observedPropertyDecorators, COMPONENT_NON_DECORATOR, COMPONENT_PROP_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR]; @@ -155,10 +163,60 @@ function addCustomComponent(node: ts.ExpressionStatement, newStatements: ts.Stat function addCustomComponentStatements(node: ts.ExpressionStatement, newStatements: ts.Statement[], newNode: ts.NewExpression, name: string, props: ts.ObjectLiteralElementLike[], isInnerBuilder: boolean = false): void { - const id: string = componentInfo.id.toString(); - newStatements.push(createFindChildById(id, name, isInnerBuilder), createCustomComponentIfStatement(id, - ts.factory.updateExpressionStatement(node, createViewCreate(newNode)), - ts.factory.createObjectLiteralExpression(props, true), name)); + if (!partialUpdateConfig.partialUpdateMode) { + const id: string = componentInfo.id.toString(); + newStatements.push(createFindChildById(id, name, isInnerBuilder), createCustomComponentIfStatement(id, + ts.factory.updateExpressionStatement(node, createViewCreate(newNode)), + ts.factory.createObjectLiteralExpression(props, true), name)); + } else { + newStatements.push(createCustomComponent(newNode)); + } +} + +function createCustomComponent(newNode: ts.NewExpression): ts.Block { + return ts.factory.createBlock( + [ + ts.factory.createVariableStatement(undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(ELMTID), undefined, undefined, + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(VIEWSTACKPROCESSOR), + ts.factory.createIdentifier(ALLOCATENEWELMETIDFORNEXTCOMPONENT) + ), undefined, []))], + ts.NodeFlags.Const + ) + ), + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(VIEWSTACKPROCESSOR), + ts.factory.createIdentifier(STARTGETACCESSRECORDINGFOR) + ), undefined, + [ts.factory.createIdentifier(ELMTID)] + ) + ), + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(BASE_COMPONENT_NAME_PU), + ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION) + ), undefined, + [newNode] + ) + ), + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(VIEWSTACKPROCESSOR), + ts.factory.createIdentifier(STOPGETACCESSRECORDING) + ), undefined, [] + ) + ) + ], + true + ); } function validateCustomComponentPrams(node: ts.CallExpression, name: string, @@ -344,7 +402,9 @@ function isCorrectInitFormParent(parent: string, child: string): boolean { } break; case COMPONENT_OBJECT_LINK_DECORATOR: - if (parent === COMPONENT_STATE_DECORATOR) { + if (!partialUpdateConfig.partialUpdateMode && parent === COMPONENT_STATE_DECORATOR) { + return true; + } else if (partialUpdateConfig.partialUpdateMode && STATE_OBJECTLINK_DECORATORS.includes(parent)) { return true; } break; diff --git a/compiler/src/process_ui_syntax.ts b/compiler/src/process_ui_syntax.ts index 233f4cf..7c170d3 100644 --- a/compiler/src/process_ui_syntax.ts +++ b/compiler/src/process_ui_syntax.ts @@ -54,7 +54,11 @@ import { COMPONENT_COMMON, EXTNAME_ETS, GENERATE_ID, - _GENERATE_ID + _GENERATE_ID, + VIEWSTACKPROCESSOR, + STARTGETACCESSRECORDINGFOR, + ALLOCATENEWELMETIDFORNEXTCOMPONENT, + STOPGETACCESSRECORDING } from './pre_define'; import { componentInfo, @@ -84,7 +88,8 @@ import { } from './validate_ui_syntax'; import { resources, - projectConfig + projectConfig, + partialUpdateConfig } from '../main'; import { createCustomComponentNewExpression, createViewCreate } from './process_component_member'; @@ -115,7 +120,9 @@ export function processUISyntax(program: ts.Program, ut = false): Function { }); GLOBAL_STYLE_FUNCTION.clear(); const statements: ts.Statement[] = Array.from(node.statements); - generateId(statements, node); + if (!partialUpdateConfig.partialUpdateMode) { + generateId(statements, node); + } INTERFACE_NODE_SET.forEach(item => { statements.unshift(item); }); @@ -581,9 +588,15 @@ export function isExtendFunction(node: ts.FunctionDeclaration): string { function createEntryNode(node: ts.SourceFile, context: ts.TransformationContext): ts.SourceFile { if (componentCollection.previewComponent.size === 0 || !projectConfig.isPreview) { if (componentCollection.entryComponent) { - const entryNode: ts.ExpressionStatement = - createEntryFunction(componentCollection.entryComponent, context); - return context.factory.updateSourceFile(node, [...node.statements, entryNode]); + if (!partialUpdateConfig.partialUpdateMode) { + const entryNode: ts.ExpressionStatement = + createEntryFunction(componentCollection.entryComponent, context) as ts.ExpressionStatement; + return context.factory.updateSourceFile(node, [...node.statements, entryNode]); + } else { + const entryNodes: ts.ExpressionStatement[] = + createEntryFunction(componentCollection.entryComponent, context) as ts.ExpressionStatement[]; + return context.factory.updateSourceFile(node, [...node.statements, ...entryNodes]); + } } else { return node; } @@ -595,7 +608,7 @@ function createEntryNode(node: ts.SourceFile, context: ts.TransformationContext) } function createEntryFunction(name: string, context: ts.TransformationContext) - : ts.ExpressionStatement { + : ts.ExpressionStatement | ts.ExpressionStatement[] { let localStorageName: string; const localStorageNum: number = localStorageLinkCollection.get(name).size + localStoragePropCollection.get(name).size; @@ -619,12 +632,71 @@ function createEntryFunction(name: string, context: ts.TransformationContext) if (localStorageName) { newArray.push(context.factory.createIdentifier(localStorageName)); } - const newExpressionStatement: ts.ExpressionStatement = - context.factory.createExpressionStatement(context.factory.createCallExpression( - context.factory.createIdentifier(PAGE_ENTRY_FUNCTION_NAME), undefined, - [context.factory.createNewExpression(context.factory.createIdentifier(name), - undefined, newArray)])); - return newExpressionStatement; + if (!partialUpdateConfig.partialUpdateMode) { + const newExpressionStatement: ts.ExpressionStatement = + context.factory.createExpressionStatement(context.factory.createCallExpression( + context.factory.createIdentifier(PAGE_ENTRY_FUNCTION_NAME), undefined, + [context.factory.createNewExpression(context.factory.createIdentifier(name), + undefined, newArray)])); + return newExpressionStatement; + } else { + return [ + createStartGetAccessRecording(context), + createLoadDocument(context, name), + createStopGetAccessRecording(context) + ]; + } +} + +function createStartGetAccessRecording(context: ts.TransformationContext): ts.ExpressionStatement { + return context.factory.createExpressionStatement( + context.factory.createCallExpression( + context.factory.createPropertyAccessExpression( + context.factory.createIdentifier(VIEWSTACKPROCESSOR), + context.factory.createIdentifier(STARTGETACCESSRECORDINGFOR) + ), + undefined, + [context.factory.createCallExpression( + context.factory.createPropertyAccessExpression( + context.factory.createIdentifier(VIEWSTACKPROCESSOR), + context.factory.createIdentifier(ALLOCATENEWELMETIDFORNEXTCOMPONENT) + ), + undefined, + [] + )] + ) + ); +} + +function createLoadDocument(context: ts.TransformationContext, name: string): ts.ExpressionStatement { + return context.factory.createExpressionStatement( + context.factory.createCallExpression( + context.factory.createIdentifier(PAGE_ENTRY_FUNCTION_NAME), + undefined, + [context.factory.createNewExpression( + context.factory.createIdentifier(name), + undefined, + [context.factory.createIdentifier('undefined'), + context.factory.createObjectLiteralExpression( + [], + false + )] + )] + ) + ); +} + +function createStopGetAccessRecording(context: ts.TransformationContext): ts.ExpressionStatement { + return context.factory.createExpressionStatement( + context.factory.createCallExpression( + context.factory.createPropertyAccessExpression( + context.factory.createIdentifier(VIEWSTACKPROCESSOR), + context.factory.createIdentifier(STOPGETACCESSRECORDING) + ), + undefined, + [] + ) + ); } function createPreviewComponentFunction(name: string, context: ts.TransformationContext) diff --git a/compiler/test/test.js b/compiler/test/test.js index 0595536..1e986e5 100644 --- a/compiler/test/test.js +++ b/compiler/test/test.js @@ -35,6 +35,9 @@ const { NATIVE_MODULE, SYSTEM_PLUGIN } = require('../lib/pre_define'); +const { + partialUpdateConfig +} = require('../main'); function expectActual(name, filePath) { const content = require(filePath); @@ -59,7 +62,11 @@ function expectActual(name, filePath) { } mocha.describe('compiler', () => { - const utPath = path.resolve(__dirname, './ut'); + let utPath = path.resolve(__dirname, './ut'); + if (process.argv.includes('--partialUpdate')) { + partialUpdateConfig.partialUpdateMode = true; + utPath = path.resolve(__dirname, './utForPartialUpdate'); + } const utFiles = []; readFile(utPath, utFiles); utFiles.forEach((item) => { diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/custom_component/custom_component.ts b/compiler/test/utForPartialUpdate/inner_component_transform/custom_component/custom_component.ts new file mode 100644 index 0000000..598d2a4 --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/custom_component/custom_component.ts @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Component +@Entry +struct MyComponent { + build() { + Column() { + Banner() + Banner() + .width(100) + Banner() + .width(100) + .height(200) + Banner({value: "Hello"}) + Banner({value: "Hello"}) + .width(100) + Banner({value: "Hello"}) + .width(100) + .height(200) + } + } +} + +@Component +struct Banner { + value: string = "Hello" + build() { + Column() { + Text(this.value) + } + } +}` + +exports.expectResult = +`"use strict"; +class MyComponent extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + } + aboutToBeDeleted() { + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new Banner(this, {})); + ViewStackProcessor.StopGetAccessRecording(); + } + __Common__.create(); + __Common__.width(100); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new Banner(this, {})); + ViewStackProcessor.StopGetAccessRecording(); + } + __Common__.pop(); + __Common__.create(); + __Common__.width(100); + __Common__.height(200); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new Banner(this, {})); + ViewStackProcessor.StopGetAccessRecording(); + } + __Common__.pop(); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new Banner(this, { value: "Hello" })); + ViewStackProcessor.StopGetAccessRecording(); + } + __Common__.create(); + __Common__.width(100); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new Banner(this, { value: "Hello" })); + ViewStackProcessor.StopGetAccessRecording(); + } + __Common__.pop(); + __Common__.create(); + __Common__.width(100); + __Common__.height(200); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new Banner(this, { value: "Hello" })); + ViewStackProcessor.StopGetAccessRecording(); + } + __Common__.pop(); + Column.pop(); + } + rerender() { + this.updateDirtyElements(); + } +} +class Banner extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.value = "Hello"; + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.value !== undefined) { + this.value = params.value; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + } + aboutToBeDeleted() { + this.value = undefined; + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(this.value); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + Column.pop(); + } + rerender() { + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new MyComponent(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/render_component/foreach/foreach.ts b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/foreach/foreach.ts new file mode 100644 index 0000000..09e3232 --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/foreach/foreach.ts @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Entry +@Component +struct ParentView { + @State arr: string[] = ['1', '2', '3']; + build() { + List() { + ForEach(this.arr, + item => { + Text(item) + }, + item => item.toString() + ) + } + } +} +` +exports.expectResult = +`"use strict"; +class ParentView extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__arr = new ObservedPropertyObjectPU(['1', '2', '3'], this, "arr"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.arr !== undefined) { + this.arr = params.arr; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__arr.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__arr.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get arr() { + return this.__arr.get(); + } + set arr(newValue) { + this.__arr.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + List.create(); + if (!isInitialRender) { + List.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ForEach.create(); + const forEachItemGenFunction = _item => { + const item = _item; + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(item); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + }; + const forEachItemIdFunc = item => item.toString(); + this.forEachUpdateFunction(elmtId, this.arr, forEachItemGenFunction, forEachItemIdFunc); + if (!isInitialRender) { + ForEach.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + ForEach.pop(); + List.pop(); + } + rerender() { + this.__arr.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new ParentView(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/render_component/if/if.ts b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/if/if.ts new file mode 100644 index 0000000..6a79a06 --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/if/if.ts @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Entry +@Component +struct IFView { + @State toggle1: boolean = false; + @State toggle2: boolean = false; + @State toggle3: boolean = false; + + build() { + Column() { + if (this.toggle1) { + Text('toggle1') + } else if(this.toggle2) { + Text('toggle2') + } else if (this.toggle3) { + Text('toggle3') + } else { + Text('toggle no thing') + } + } + } +} +` +exports.expectResult = +`"use strict"; +class IFView extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__toggle1 = new ObservedPropertySimplePU(false, this, "toggle1"); + this.__toggle2 = new ObservedPropertySimplePU(false, this, "toggle2"); + this.__toggle3 = new ObservedPropertySimplePU(false, this, "toggle3"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.toggle1 !== undefined) { + this.toggle1 = params.toggle1; + } + if (params.toggle2 !== undefined) { + this.toggle2 = params.toggle2; + } + if (params.toggle3 !== undefined) { + this.toggle3 = params.toggle3; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__toggle1.purgeDependencyOnElmtId(rmElmtId); + this.__toggle2.purgeDependencyOnElmtId(rmElmtId); + this.__toggle3.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__toggle1.aboutToBeDeleted(); + this.__toggle2.aboutToBeDeleted(); + this.__toggle3.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get toggle1() { + return this.__toggle1.get(); + } + set toggle1(newValue) { + this.__toggle1.set(newValue); + } + get toggle2() { + return this.__toggle2.get(); + } + set toggle2(newValue) { + this.__toggle2.set(newValue); + } + get toggle3() { + return this.__toggle3.get(); + } + set toggle3(newValue) { + this.__toggle3.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + If.create(); + if (this.toggle1) { + If.branchId(0); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('toggle1'); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + } + else if (this.toggle2) { + If.branchId(1); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('toggle2'); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + } + else if (this.toggle3) { + If.branchId(2); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('toggle3'); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + } + else { + If.branchId(3); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('toggle no thing'); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + } + if (!isInitialRender) { + If.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + If.pop(); + Column.pop(); + } + rerender() { + this.__toggle1.markDependentElementsDirty(this); + this.__toggle2.markDependentElementsDirty(this); + this.__toggle3.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new IFView(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/render_component/item/GridItem.ts b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/item/GridItem.ts new file mode 100644 index 0000000..2988c7f --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/item/GridItem.ts @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Entry +@Component +struct ParentView { + build() { + Grid() { + GridItem('true') { + Text('xx').width(100) + }.width(200).height(100) + } + } +} +` +exports.expectResult = +`"use strict"; +class ParentView extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + } + aboutToBeDeleted() { + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Grid.create(); + if (!isInitialRender) { + Grid.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + { + const isLazyCreate = true && (Grid.willUseProxy() === true); + const itemCreation = (elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + GridItem.create(deepRenderFunction, isLazyCreate); + GridItem.width(200); + GridItem.height(100); + if (!isInitialRender) { + GridItem.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }; + const observedShallowRender = () => { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + GridItem.create(deepRenderFunction, isLazyCreate); + if (!isInitialRender) { + GridItem.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + GridItem.pop(); + }; + const observedDeepRender = () => { + this.observeComponentCreation(itemCreation); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('xx'); + Text.width(100); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + GridItem.pop(); + }; + const deepRenderFunction = (elmtId, isInitialRender) => { + itemCreation(elmtId, isInitialRender); + this.updateFuncByElmtId.set(elmtId, itemCreation); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('xx'); + Text.width(100); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + GridItem.pop(); + }; + if (isLazyCreate) { + observedShallowRender(); + } + else { + observedDeepRender(); + } + } + Grid.pop(); + } + rerender() { + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new ParentView(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/render_component/item/ListItem.ts b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/item/ListItem.ts new file mode 100644 index 0000000..ae8cbcd --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/item/ListItem.ts @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Entry +@Component +struct ParentView { + build() { + List() { + ListItem('true') { + Text('xx').width(100) + }.width(200).height(100) + } + } +} +` +exports.expectResult = +`"use strict"; +class ParentView extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + } + aboutToBeDeleted() { + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + List.create(); + if (!isInitialRender) { + List.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + { + const isLazyCreate = true; + const itemCreation = (elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ListItem.create(deepRenderFunction, isLazyCreate); + ListItem.width(200); + ListItem.height(100); + if (!isInitialRender) { + ListItem.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }; + const observedShallowRender = () => { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ListItem.create(deepRenderFunction, isLazyCreate); + if (!isInitialRender) { + ListItem.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + ListItem.pop(); + }; + const observedDeepRender = () => { + this.observeComponentCreation(itemCreation); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('xx'); + Text.width(100); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + ListItem.pop(); + }; + const deepRenderFunction = (elmtId, isInitialRender) => { + itemCreation(elmtId, isInitialRender); + this.updateFuncByElmtId.set(elmtId, itemCreation); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('xx'); + Text.width(100); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + ListItem.pop(); + }; + if (isLazyCreate) { + observedShallowRender(); + } + else { + observedDeepRender(); + } + } + List.pop(); + } + rerender() { + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new ParentView(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/render_component/lazyforeach/lazyforeach.ts b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/lazyforeach/lazyforeach.ts new file mode 100644 index 0000000..102dd68 --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/lazyforeach/lazyforeach.ts @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +class BasicDataSource implements IDataSource { + private listeners: DataChangeListener[] = [] + + public totalCount(): number { + return 0 + } + public getData(index: number): any { + return undefined + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener') + this.listeners.push(listener) + } + } + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener') + this.listeners.splice(pos, 1) + } + } + + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded() + }) + } + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index) + }) + } + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index) + }) + } + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index) + }) + } + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to) + }) + } +} + +class MyDataSource extends BasicDataSource { + private dataArray: string[] = ['/path/image0', '/path/image1', '/path/image2', '/path/image3'] + + public totalCount(): number { + return this.dataArray.length + } + public getData(index: number): any { + return this.dataArray[index] + } + + public addData(index: number, data: string): void { + this.dataArray.splice(index, 0, data) + this.notifyDataAdd(index) + } + public pushData(data: string): void { + this.dataArray.push(data) + this.notifyDataAdd(this.dataArray.length - 1) + } +} + +@Entry +@Component +struct Test { +private data: MyDataSource = new MyDataSource() +build() { + Grid() { + LazyForEach (this.data, + (row) => { + GridItem() { + Text(row) + } + }, + row => row) + } +} +} +` +exports.expectResult = +`"use strict"; +class BasicDataSource { + constructor() { + this.listeners = []; + } + totalCount() { + return 0; + } + getData(index) { + return undefined; + } + registerDataChangeListener(listener) { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener'); + this.listeners.push(listener); + } + } + unregisterDataChangeListener(listener) { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener'); + this.listeners.splice(pos, 1); + } + } + notifyDataReload() { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }); + } + notifyDataAdd(index) { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }); + } + notifyDataChange(index) { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }); + } + notifyDataDelete(index) { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }); + } + notifyDataMove(from, to) { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }); + } +} +class MyDataSource extends BasicDataSource { + constructor() { + super(...arguments); + this.dataArray = ['/path/image0', '/path/image1', '/path/image2', '/path/image3']; + } + totalCount() { + return this.dataArray.length; + } + getData(index) { + return this.dataArray[index]; + } + addData(index, data) { + this.dataArray.splice(index, 0, data); + this.notifyDataAdd(index); + } + pushData(data) { + this.dataArray.push(data); + this.notifyDataAdd(this.dataArray.length - 1); + } +} +class Test extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.data = new MyDataSource(); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.data !== undefined) { + this.data = params.data; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + } + aboutToBeDeleted() { + this.data = undefined; + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Grid.create(); + if (!isInitialRender) { + Grid.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + { + const __lazyForEachItemGenFunction = _item => { + const row = _item; + { + const isLazyCreate = (globalThis.__lazyForEachItemGenFunction !== undefined) && true && (Grid.willUseProxy() === true); + const itemCreation = (elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + GridItem.create(deepRenderFunction, isLazyCreate); + if (!isInitialRender) { + GridItem.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }; + const observedShallowRender = () => { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + GridItem.create(deepRenderFunction, isLazyCreate); + if (!isInitialRender) { + GridItem.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + GridItem.pop(); + }; + const observedDeepRender = () => { + this.observeComponentCreation(itemCreation); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(row); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + GridItem.pop(); + }; + const deepRenderFunction = (elmtId, isInitialRender) => { + itemCreation(elmtId, isInitialRender); + this.updateFuncByElmtId.set(elmtId, itemCreation); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(row); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + GridItem.pop(); + }; + if (isLazyCreate) { + observedShallowRender(); + } + else { + observedDeepRender(); + } + } + }; + const __lazyForEachItemIdFunc = row => row; + LazyForEach.create("1", this, this.data, __lazyForEachItemGenFunction, __lazyForEachItemIdFunc); + LazyForEach.pop(); + } + Grid.pop(); + } + rerender() { + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new Test(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/inner_component_transform/render_component/tab/tab.ts b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/tab/tab.ts new file mode 100644 index 0000000..f531e56 --- /dev/null +++ b/compiler/test/utForPartialUpdate/inner_component_transform/render_component/tab/tab.ts @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Entry +@Component +struct TabSimple { + private controller: TabsController = new TabsController(); + build() { + Column() { + Tabs({ barPosition: BarPosition.Start, index: 1, controller: this.controller}) { + TabContent() { + Flex() { + Column() { + Text('text1') + .height(100) + .width(200) + Text('xxx') + .height(100) + .width(200) + } + .height(100) + .width(200) + } + .height(100) + .width(200) + } + .tabBar("TabBar") + .height(100) + .width(200) + TabContent() { + Text('text2') + } + .tabBar("TabBar 2") + .height(100) + .width(200) + } + } + } +} +` +exports.expectResult = +`"use strict"; +class TabSimple extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.controller = new TabsController(); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.controller !== undefined) { + this.controller = params.controller; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + } + aboutToBeDeleted() { + this.controller = undefined; + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Tabs.create({ barPosition: BarPosition.Start, index: 1, controller: this.controller }); + if (!isInitialRender) { + Tabs.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + TabContent.create(() => { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Flex.create(); + Flex.height(100); + Flex.width(200); + if (!isInitialRender) { + Flex.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + Column.height(100); + Column.width(200); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('text1'); + Text.height(100); + Text.width(200); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('xxx'); + Text.height(100); + Text.width(200); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + Column.pop(); + Flex.pop(); + }); + TabContent.tabBar("TabBar"); + TabContent.height(100); + TabContent.width(200); + if (!isInitialRender) { + TabContent.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + TabContent.pop(); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + TabContent.create(() => { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create('text2'); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + }); + TabContent.tabBar("TabBar 2"); + TabContent.height(100); + TabContent.width(200); + if (!isInitialRender) { + TabContent.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + TabContent.pop(); + Tabs.pop(); + Column.pop(); + } + rerender() { + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new TabSimple(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@link/@link.ts b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@link/@link.ts new file mode 100644 index 0000000..aaef837 --- /dev/null +++ b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@link/@link.ts @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Component +struct LinkComponent { + @Link counter: string + build() { + Text(this.counter) + } +} + +@Entry +@Component +struct ParentComponent { + @State value: string = 'first init content'; + build() { + Column() { + LinkComponent({counter: this.$value}) + } + } +} +` +exports.expectResult = +`"use strict"; +class LinkComponent extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__counter = new SynchedPropertySimpleTwoWayPU(params.counter, this, "counter"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__counter.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__counter.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get counter() { + return this.__counter.get(); + } + set counter(newValue) { + this.__counter.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(this.counter); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + } + rerender() { + this.__counter.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +class ParentComponent extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__value = new ObservedPropertySimplePU('first init content', this, "value"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.value !== undefined) { + this.value = params.value; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__value.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__value.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get value() { + return this.__value.get(); + } + set value(newValue) { + this.__value.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new LinkComponent(this, { counter: this.__value })); + ViewStackProcessor.StopGetAccessRecording(); + } + Column.pop(); + } + rerender() { + this.__value.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new ParentComponent(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@objectLink/@objectLink.ts b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@objectLink/@objectLink.ts new file mode 100644 index 0000000..1b92a88 --- /dev/null +++ b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@objectLink/@objectLink.ts @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +var nextID: number = 0; +@Observed +class Model { + text : string = ''; + color: string = '#00ff00'; + constructor(t: string, c: string) { + this.text = t; + this.color = c; + } +} + +@Component +struct CustomText { + @ObjectLink model: Model; + build() { + Row() { + Text(this.model.text) + } + } +} + +@Entry +@Component +struct Parent { + nextId: number = 1; + @State models : Model[] = [ new Model('0', '#ffffff'), new Model('1', '#fff456') ]; + build() { + Column() { + ForEach (this.models, (item) => { + CustomText({model: item}) + }, + (item) => item.text + ) + } + } +} +` +exports.expectResult = +`"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var nextID = 0; +let Model = class Model { + constructor(t, c) { + this.text = ''; + this.color = '#00ff00'; + this.text = t; + this.color = c; + } +}; +Model = __decorate([ + Observed +], Model); +class CustomText extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__model = new SynchedPropertyNesedObjectPU(params.model, this, "model"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + this.__model.set(params.model); + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__model.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__model.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get model() { + return this.__model.get(); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Row.create(); + if (!isInitialRender) { + Row.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(this.model.text); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + Row.pop(); + } + rerender() { + this.__model.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +class Parent extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.nextId = 1; + this.__models = new ObservedPropertyObjectPU([new Model('0', '#ffffff'), new Model('1', '#fff456')], this, "models"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.nextId !== undefined) { + this.nextId = params.nextId; + } + if (params.models !== undefined) { + this.models = params.models; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__models.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.nextId = undefined; + this.__models.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get models() { + return this.__models.get(); + } + set models(newValue) { + this.__models.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ForEach.create(); + const forEachItemGenFunction = _item => { + const item = _item; + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new CustomText(this, { model: item })); + ViewStackProcessor.StopGetAccessRecording(); + } + }; + const forEachItemIdFunc = item => item.text; + this.forEachUpdateFunction(elmtId, this.models, forEachItemGenFunction, forEachItemIdFunc); + if (!isInitialRender) { + ForEach.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + ForEach.pop(); + Column.pop(); + } + rerender() { + this.__models.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new Parent(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@prop/@prop.ts b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@prop/@prop.ts new file mode 100644 index 0000000..a74de3a --- /dev/null +++ b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@prop/@prop.ts @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Component +struct PropComponent { + @Prop counter: string + build() { + Text(this.counter) + } +} + +@Entry +@Component +struct ParentComponent { + @State value: string = 'first init content'; + build() { + Column() { + PropComponent({counter: this.value}) + } + } +} +` +exports.expectResult = +`"use strict"; +class PropComponent extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__counter = new SynchedPropertySimpleOneWayPU(params.counter, this, "counter"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__counter.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__counter.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get counter() { + return this.__counter.get(); + } + set counter(newValue) { + this.__counter.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create(this.counter); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + } + rerender() { + this.__counter.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +class ParentComponent extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__value = new ObservedPropertySimplePU('first init content', this, "value"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.value !== undefined) { + this.value = params.value; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__value.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__value.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get value() { + return this.__value.get(); + } + set value(newValue) { + this.__value.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + { + const elmtId = ViewStackProcessor.AllocateNewElmetIdForNextComponent(); + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + ViewPU.create(new PropComponent(this, { counter: this.__value })); + ViewStackProcessor.StopGetAccessRecording(); + } + Column.pop(); + } + rerender() { + this.__value.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new ParentComponent(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +` \ No newline at end of file diff --git a/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@state/@state.ts b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@state/@state.ts new file mode 100644 index 0000000..c895d07 --- /dev/null +++ b/compiler/test/utForPartialUpdate/ui_state_management/inner_struct_state_management/@state/@state.ts @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +@Entry +@Component +struct StatePage { + @State counter: number = 0; + build() { + Column() { + Text("counter:" + this.counter) + } + } +} +` +exports.expectResult = +`"use strict"; +class StatePage extends ViewPU { + constructor(parent, params, __localStorage) { + super(parent, __localStorage); + this.__counter = new ObservedPropertySimplePU(0, this, "counter"); + this.setInitiallyProvidedValue(params); + } + setInitiallyProvidedValue(params) { + if (params.counter !== undefined) { + this.counter = params.counter; + } + } + purgeVariableDependenciesOnElmtId(rmElmtId) { + this.__counter.purgeDependencyOnElmtId(rmElmtId); + } + aboutToBeDeleted() { + this.__counter.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id__()); + this.aboutToBeDeletedInternal(); + } + get counter() { + return this.__counter.get(); + } + set counter(newValue) { + this.__counter.set(newValue); + } + initialRender() { + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Column.create(); + if (!isInitialRender) { + Column.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + this.observeComponentCreation((elmtId, isInitialRender) => { + ViewStackProcessor.StartGetAccessRecordingFor(elmtId); + Text.create("counter:" + this.counter); + if (!isInitialRender) { + Text.pop(); + } + ViewStackProcessor.StopGetAccessRecording(); + }); + Text.pop(); + Column.pop(); + } + rerender() { + this.__counter.markDependentElementsDirty(this); + this.updateDirtyElements(); + } +} +ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent()); +loadDocument(new StatePage(undefined, {})); +ViewStackProcessor.StopGetAccessRecording(); +`