Skip to content

Commit 331cc9c

Browse files
[v9] fix: only copy props if same constructor (#3429)
1 parent b3e4ee4 commit 331cc9c

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

packages/fiber/src/core/utils.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ const colorMaps = ['map', 'emissiveMap', 'sheenColorMap', 'specularColorMap', 'e
365365

366366
const EVENT_REGEX = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/
367367

368+
type ClassConstructor = { new (): void }
369+
368370
// This function applies a set of changes to the instance
369371
export function applyProps<T = any>(object: Instance<T>['object'], props: Instance<T>['props']): Instance<T>['object'] {
370372
const instance = object.__r3f
@@ -391,7 +393,11 @@ export function applyProps<T = any>(object: Instance<T>['object'], props: Instan
391393
let { root, key, target } = resolve(object, prop)
392394

393395
// Copy if properties match signatures
394-
if (typeof target?.copy === 'function' && target.copy === (value as any).copy) {
396+
if (
397+
target?.copy &&
398+
(value as ClassConstructor | undefined)?.constructor &&
399+
(target as ClassConstructor).constructor === (value as ClassConstructor).constructor
400+
) {
395401
target.copy(value)
396402
}
397403
// Layers have no copy function, we must therefore copy the mask property

packages/fiber/tests/utils.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,27 @@ describe('applyProps', () => {
417417

418418
expect(target.value).toBe('initial')
419419
})
420+
421+
it('should not copy if props are supersets of another', async () => {
422+
const copy = jest.fn()
423+
424+
class Material {
425+
copy = copy
426+
}
427+
class SuperMaterial extends Material {
428+
copy = copy
429+
}
430+
431+
const one = new Material()
432+
const two = new SuperMaterial()
433+
434+
const target = { material: one }
435+
applyProps(target, { material: two })
436+
437+
expect(one.copy).not.toHaveBeenCalled()
438+
expect(two.copy).not.toHaveBeenCalled()
439+
expect(target.material).toBe(two)
440+
})
420441
})
421442

422443
describe('updateCamera', () => {

0 commit comments

Comments
 (0)