Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting onBeforeCompile on derived material may cause infinite recursion #347

Open
brianchirls opened this issue Dec 11, 2024 · 0 comments

Comments

@brianchirls
Copy link

If you set onBeforeCompile to itself or to that of another derived material, the setter for that property will assign it to this[privateBeforeCompileProp], and the function will call itself infinitely.

For example:

const customMaterial = createDerivedMaterial(
  baseMaterial,
  {
    // ...
  }
)
const clonedMaterial = customMaterial.clone()
clonedMaterial.onBeforeCompile = customMaterial.onBeforeCompile;

The reason this came up for me is that I needed to clone some materials, including the callbacks. Three.js Material .clone() does not copy callbacks, so I had to write my own code to do it. I tried checking with Object.hasOwn to avoid copying the callback function if it's on the prototype, but it doesn't work here. So I can't find a good workaround.

You could easily check against setting the function to itself by making a change like this:

    onBeforeCompile: {
      get() {
        return onBeforeCompile
      },
      set(fn) {
        if (fn !== onBeforeCompile) {
          this[privateBeforeCompileProp] = fn;
        }
      }
    },

...but that won't work if you copy it over from another material. Another option might be to put every internal onBeforeCompile function in a shared WeakSet and check that. Or tag it somehow by adding a property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant