diff --git a/ets-tests/ets/AllPages.ets b/ets-tests/ets/AllPages.ets index 9f6b56daa96d6581458af952ee9fd7bbc5a68ef6..0e29ddf0a60ca5bef7ccfdedba47624a72927e10 100644 --- a/ets-tests/ets/AllPages.ets +++ b/ets-tests/ets/AllPages.ets @@ -37,6 +37,8 @@ import { PropMutateTest } from "./pages/props/PropMutateTest" import { PropStringTest } from "./pages/props/PropStringTest" import { PropBoolTest } from "./pages/props/PropBoolTest" import { PropLocalInitTest } from "./pages/props/PropLocalInitTest" +import { PropSetTest } from "./pages/props/PropSetTest" +import { PropMapTest } from "./pages/props/PropMapTest" import { ProvideConsumeBaseTest } from "./pages/provide/ProvideConsumeBaseTest" import { ProvideConsumeObject } from "./pages/provide/ProvideConsumeObject" import { ProvideConsumeChildTest } from "./pages/provide/ProvideConsumeChildTest" @@ -94,6 +96,8 @@ function pageByName(name: string): void { case "PropStringTest": PropStringTest(); break case "PropBoolTest": PropBoolTest(); break case "PropLocalInitTest": PropLocalInitTest(); break + case "PropSetTest": PropSetTest(); break + case "PropMapTest": PropMapTest(); break case "ProvideConsumeBaseTest": ProvideConsumeBaseTest(); break case "ProvideConsumeObject": ProvideConsumeObject(); break case "ProvideConsumeChildTest": ProvideConsumeChildTest(); break diff --git a/ets-tests/ets/pages/props/PropMapTest.ets b/ets-tests/ets/pages/props/PropMapTest.ets new file mode 100644 index 0000000000000000000000000000000000000000..6ba5caf75273b32dfe7999aeef86bf2e5abee160 --- /dev/null +++ b/ets-tests/ets/pages/props/PropMapTest.ets @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 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. + */ + +@Component +export struct MapChild { + @Prop items: Map + + build() { + TestComponent({ id: 405 }).onChange(() => { + this.items.delete("a") + }) + TestComponent().log(`child map: ${JSON.stringify(Array.from(this.items.entries()))}`) + } +} + +@Entry +@Component +export struct PropMapTest { + @State items: Map = new Map([["a", 1]]) + + build() { + TestComponent({ id: 404 }).onChange(() => { + const updated = new Map(this.items) + updated.set("b", 2) + this.items = updated + }) + + TestComponent().log(`Parent sees: ${JSON.stringify(Array.from(this.items.entries()))}`) + + MapChild({ items: this.items }) + + TestComponent().log(`Parent sees: ${JSON.stringify(Array.from(this.items.entries()))}`) + } +} diff --git a/ets-tests/ets/pages/props/PropSetTest.ets b/ets-tests/ets/pages/props/PropSetTest.ets new file mode 100644 index 0000000000000000000000000000000000000000..49d45deb8ca7a24012b0a8a6821685c1aedbbd23 --- /dev/null +++ b/ets-tests/ets/pages/props/PropSetTest.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 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. + */ + +@Component +export struct SetChild { + @Prop items: Set + + build() { + TestComponent({ id: 402 }).onChange(() => { + this.items.delete("a") + }) + TestComponent().log(`child set: ${JSON.stringify(Array.from(this.items))}`) + } +} + +@Entry +@Component +export struct PropSetTest { + @State items: Set = new Set(["a"]) + + build() { + TestComponent({ id: 402 }) + .onChange(() => { + const updated = new Set(this.items) + updated.add("b") + this.items = updated + }) + + TestComponent().log(`Parent sees: ${JSON.stringify(Array.from(this.items))}`) + + SetChild({ items: this.items }) + + TestComponent().log(`Parent sees: ${JSON.stringify(Array.from(this.items))}`) + } +} diff --git a/ets-tests/ets/suites/PropDecorator.ets b/ets-tests/ets/suites/PropDecorator.ets index b72d4885d92303cb7ca82a9e1e8644e9dace8af1..4fb58683362f8ddc6697e5c5147f52f2dc43eef5 100644 --- a/ets-tests/ets/suites/PropDecorator.ets +++ b/ets-tests/ets/suites/PropDecorator.ets @@ -107,7 +107,7 @@ export function propDecoratorBehaviorTest(control: AppControl) { "child.value = 10\n", "Child's local default was not overridden by parent @Prop") }) - + /* Array mutation from parent vs. child @@ -145,6 +145,44 @@ export function propDecoratorBehaviorTest(control: AppControl) { "Parent sees: Sat Jan 02 1999\n", "@Prop Date was mutated by child, violating one-way data flow") }) + + /* + Set mutation: parent vs. child + + Verifies: + - Parent adds to a Set and child sees the new element. + - Child deletes an element — and this affects the parent (unexpected). + + Example: PropSetTest + */ + test.expectFailure("Set: parent add() works, child delete() not", () => { + testPageOnChange(control, "PropSetTest", [402, 403], + 'Parent sees: ["a"]\n' + + 'parent set: ["a","b"]\n' + + 'Parent sees: ["a","b"]\n' + + 'child set: ["b"]\n' + + 'Parent sees: ["a","b"]\n', + "@Prop Set was mutated by child, violating one-way data flow") + }) + + /* + Map mutation: parent vs. child + + Verifies: + - Parent can add to a Map and child sees the update. + - Child attempts to delete a key — this must NOT affect the parent's state. + + Example: PropMapTest + */ + test.expectFailure("Map: parent set() works, child delete() not", () => { + testPageOnChange(control, "PropMapTest", [404, 405], + 'Parent sees: [["a",1]]\n' + + 'parent map: [["a",1],["b",2]]\n' + + 'Parent sees: [["a",1],["b",2]]\n' + + 'child map: [["b",2]]\n' + + 'Parent sees: [["a",1],["b",2]]\n', + "@Prop Map was mutated by child, violating one-way data flow") + }) }) }