From 752b5db6bc0a45fed2df961202f5e48f90319df6 Mon Sep 17 00:00:00 2001 From: Wouter van den Heuvel Date: Fri, 25 Jul 2025 01:21:13 +0200 Subject: [PATCH] introduce safeAssign that will assign properties if not readonly --- src/core/createRoot.tsx | 15 ++------------- src/helpers/applyProps.ts | 7 +++---- src/helpers/isReadOnlyProperty.ts | 17 +++++++++++++---- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/core/createRoot.tsx b/src/core/createRoot.tsx index 3056a94c..00131a9a 100644 --- a/src/core/createRoot.tsx +++ b/src/core/createRoot.tsx @@ -3,7 +3,7 @@ import { type ApplicationOptions } from 'pixi.js'; import { type ReactNode } from 'react'; import { ConcurrentRoot } from 'react-reconciler/constants.js'; import { ContextProvider } from '../components/Context'; -import { isReadOnlyProperty } from '../helpers/isReadOnlyProperty'; +import { safeAssign } from '../helpers/isReadOnlyProperty'; import { log } from '../helpers/log'; import { prepareInstance } from '../helpers/prepareInstance'; import { type ApplicationState } from '../typedefs/ApplicationState'; @@ -92,18 +92,7 @@ export function createRoot( Object.entries(applicationOptions).forEach(([key, value]) => { - const typedKey = key as keyof ApplicationOptions; - - if (isReadOnlyProperty( - applicationOptions as unknown as Record, - typedKey, - )) - { - return; - } - - // @ts-expect-error Typescript doesn't realise it, but we're already verifying that this isn't a readonly key. - applicationState.app[typedKey] = value; + safeAssign(applicationState.app, key as keyof typeof applicationState.app, value); }); // Update fiber and expose Pixi.js state to children diff --git a/src/helpers/applyProps.ts b/src/helpers/applyProps.ts index 2073845a..b66872e3 100644 --- a/src/helpers/applyProps.ts +++ b/src/helpers/applyProps.ts @@ -19,7 +19,7 @@ import { } from './compare'; import { diffProps } from './diffProps'; import { isDiffSet } from './isDiffSet'; -import { isReadOnlyProperty } from './isReadOnlyProperty'; +import { safeAssign } from './isReadOnlyProperty'; import { log } from './log'; const DEFAULT = '__default'; @@ -174,10 +174,9 @@ export function applyProps( delete currentInstance[pixiKey]; } } - else if (!isReadOnlyProperty(currentInstance as Record, key)) + else { - // @ts-expect-error Typescript is grumpy because this could be setting a readonly key, but we're already handling that in the conditional above. 🤷🏻‍♂️ - currentInstance[key] = value; + safeAssign(currentInstance, key, value as typeof currentInstance[keyof typeof currentInstance]); } } diff --git a/src/helpers/isReadOnlyProperty.ts b/src/helpers/isReadOnlyProperty.ts index a2fcbf39..18f0d7b6 100644 --- a/src/helpers/isReadOnlyProperty.ts +++ b/src/helpers/isReadOnlyProperty.ts @@ -1,10 +1,19 @@ -export function isReadOnlyProperty( - objectInstance: Record, - propertyKey: string, -) +export function isReadOnlyProperty( + objectInstance: T, + propertyKey: keyof T, +): boolean { const prototype = Object.getPrototypeOf(objectInstance); const propertyDescriptor = Object.getOwnPropertyDescriptor(prototype, propertyKey); return !(typeof propertyDescriptor === 'undefined' || propertyDescriptor.writable || propertyDescriptor.set); } + +/** Attempts to assign the `value` to the `key` within `obj`, but only when `key` is *not* a readonly prop */ +export function safeAssign(obj: T, key: keyof T, value: T[keyof T]) +{ + if (!isReadOnlyProperty(obj, key)) + { + obj[key] = value; + } +}