From 3539db86f970ea1ea262e8b7cadb02b3dc4342c0 Mon Sep 17 00:00:00 2001 From: Peter Z Date: Mon, 14 Apr 2025 10:40:20 +0300 Subject: [PATCH] Check `allowOverride` when overriding a @Provided value --- arkoala-arkts/arkui-common/src/ArkState.ts | 9 +++++++-- arkoala-arkts/ets-plugin/src/StructTransformer.ts | 11 ++++++++++- arkoala-arkts/ets-plugin/src/utils.ts | 13 ++++++++----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arkoala-arkts/arkui-common/src/ArkState.ts b/arkoala-arkts/arkui-common/src/ArkState.ts index d45c3cda4a..92573c2ad3 100644 --- a/arkoala-arkts/arkui-common/src/ArkState.ts +++ b/arkoala-arkts/arkui-common/src/ArkState.ts @@ -14,7 +14,7 @@ */ import { observableProxy, propDeepCopy } from "@koalaui/common" -import { MutableState, __context, __id, mutableState, scheduleCallback } from "@koalaui/runtime" +import { MutableState, __context, __id, mutableState, once, scheduleCallback } from "@koalaui/runtime" /** * @param name - a name of a context state @@ -23,7 +23,12 @@ import { MutableState, __context, __id, mutableState, scheduleCallback } from "@ * @internal */ /** @memo:intrinsic */ -export function contextLocalStateOf(name: string, supplier: () => Value): MutableState { +export function contextLocalStateOf(name: string, supplier: () => Value, allowOverride: boolean = false): MutableState { + if (!allowOverride) + once(() => { + const exists = __context().stateBy(name, false) + if (exists) throw new Error("state(" + name + ") overrides another state without 'allowOverride'") + }) return __context().namedState(name, () => observableProxy(supplier())) } diff --git a/arkoala-arkts/ets-plugin/src/StructTransformer.ts b/arkoala-arkts/ets-plugin/src/StructTransformer.ts index aafafaf280..f1508a148b 100644 --- a/arkoala-arkts/ets-plugin/src/StructTransformer.ts +++ b/arkoala-arkts/ets-plugin/src/StructTransformer.ts @@ -219,6 +219,15 @@ export class StructTransformer extends AbstractVisitor { } else { throw new Error("Expected an initialization for @Provide " + deduceProvideName(provide)) } + const allowOverride = provide.modifiers + ?.filter(ts.isDecorator) + .map(dec => dec.expression) + .filter(ts.isCallExpression) + .flatMap(call => call.arguments) + .filter(ts.isObjectLiteralExpression) + .flatMap(expr => expr.properties) + .find(prop => ts.isPropertyAssignment(prop) && prop.name.getText() === "allowOverride") + return ts.factory.createVariableStatement( undefined, ts.factory.createVariableDeclarationList([ @@ -226,7 +235,7 @@ export class StructTransformer extends AbstractVisitor { provideVariableName(provide), undefined, undefined, - contextLocalStateOf(deduceProvideName(provide), initializer, provide.type) + contextLocalStateOf(deduceProvideName(provide), initializer, provide.type, isDefined(allowOverride)) ) ], ts.NodeFlags.Const diff --git a/arkoala-arkts/ets-plugin/src/utils.ts b/arkoala-arkts/ets-plugin/src/utils.ts index dbfc7988ab..af58cbaabd 100644 --- a/arkoala-arkts/ets-plugin/src/utils.ts +++ b/arkoala-arkts/ets-plugin/src/utils.ts @@ -430,14 +430,17 @@ export function filterModifiers(node: ts.Node): readonly ts.Modifier[] | undefin return ts.getModifiers(node) } -export function contextLocalStateOf(name: string, initializer: ts.Expression, type?: ts.TypeNode): ts.Expression { +export function contextLocalStateOf(name: string, initializer: ts.Expression, type?: ts.TypeNode, allowOverride?: boolean): ts.Expression { + const callParams: ts.Expression[] = [ + ts.factory.createStringLiteral(name), + createArrowFunction(initializer), + ] + if (allowOverride) + callParams.push(ts.factory.createTrue()) return ts.factory.createCallExpression( id("contextLocalStateOf"), type ? [type] : undefined, - [ - ts.factory.createStringLiteral(name), - createArrowFunction(initializer) - ] + callParams ) } -- Gitee