diff --git a/arkoala-arkts/arkui-common/src/ArkState.ts b/arkoala-arkts/arkui-common/src/ArkState.ts index d45c3cda4a099697906309c01f31af8f5a1be4f0..92573c2ad3eb5bbc0fa06986f4f277dc1327137a 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 aafafaf28080b3a3842e07e2fefd41f15e470bc9..f1508a148bb457e4d65d58a00d9a1a2640cf53ab 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 dbfc7988abc58cfa4326a17b45e5e67fdf2b545a..af58cbaabd55c84c542cfc4c860203c4e1f747ec 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 ) }