Skip to content

Commit

Permalink
Don't mutate uiSchema in normalizeModOptionsDefinition (#8679)
Browse files Browse the repository at this point in the history
  • Loading branch information
twschiller authored Jun 23, 2024
1 parent d4fd591 commit 1f5461b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
23 changes: 23 additions & 0 deletions src/utils/modUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { modComponentFactory } from "@/testUtils/factories/modComponentFactories
import { sharingDefinitionFactory } from "@/testUtils/factories/registryFactories";
import { defaultModDefinitionFactory } from "@/testUtils/factories/modDefinitionFactories";
import { InvalidTypeError } from "@/errors/genericErrors";
import { type ModOptionsDefinition } from "@/types/modDefinitionTypes";
import { freeze } from "@/utils/objectUtils";

describe("getSharingType", () => {
test("throws on invalid type", () => {
Expand Down Expand Up @@ -198,6 +200,27 @@ describe("normalizeModOptionsDefinition", () => {
});
});

it("normalizes frozen object with no ui:order", () => {
// Root cause of https://github.com/pixiebrix/pixiebrix-app/issues/5396
const original = freeze({
schema: {
type: "object",
properties: freeze({}),
},
uiSchema: freeze({}),
}) satisfies ModOptionsDefinition;

expect(normalizeModOptionsDefinition(original)).toStrictEqual({
schema: {
type: "object",
properties: {},
},
uiSchema: {
"ui:order": ["*"],
},
});
});

it("normalizes legacy schema", () => {
expect(
normalizeModOptionsDefinition({
Expand Down
4 changes: 2 additions & 2 deletions src/utils/modUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
minimalUiSchemaFactory,
propertiesToSchema,
} from "@/utils/schemaUtils";
import { mapValues, sortBy } from "lodash";
import { cloneDeep, mapValues, sortBy } from "lodash";
import { isNullOrBlank } from "@/utils/stringUtils";
import {
type Schema,
Expand Down Expand Up @@ -387,7 +387,7 @@ export function normalizeModOptionsDefinition(
Object.keys(modDefinitionSchema as SchemaProperties),
);

const uiSchema: UiSchema = optionsDefinition.uiSchema ?? {};
const uiSchema: UiSchema = cloneDeep(optionsDefinition.uiSchema ?? {});

uiSchema["ui:order"] ??= [
...sortBy(Object.keys(schema.properties ?? {})),
Expand Down
5 changes: 5 additions & 0 deletions src/utils/objectUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ export function isUnknownObjectArray(value: unknown): value is UnknownObject[] {
return Array.isArray(value) && value.every((element) => isObject(element));
}

/**
* Type helper for Object.freeze. Note that this only freezes the top level of the object.
* @see Object.freeze
*/
export function freeze<T>(value: T): T {
// Consider supporting deep freeze a la: https://www.npmjs.com/package/deep-freeze-strict
return Object.freeze(value);
}

0 comments on commit 1f5461b

Please sign in to comment.