Kinrany / vue-p5

Vue component for p5.js
125 stars 16 forks source link

Critical problem when using ".createGraphics()" #26

Open lorenzki opened 4 years ago

lorenzki commented 4 years ago

Thanks for your package - it has been quite helpful!

But now i stumbled upon a serious issue with my application.

I am using "createGraphics()" to create an imageMask. Everything works fine on the first load. But when I leave the route with "vue-p5" of my Vue application and then re-enter it, it seems like p5 crashes:

[Vue warn]: Error in mounted hook: "TypeError: b.prototype._registeredMethods[u].slice is not a function"

found in

VueP5

TypeError: b.prototype._registeredMethods[u].slice is not a function at new b (vue-p5.js?e25d:24) at VueComponent.mounted (vue-p5.js?e25d:75)

I've tried to put .createGraphics() into the preload-, the setup, or the draw-method. It's the same everywhere. On the first load everything works fine - leaving and re-entering the route crashes vue-p5.

This seems closely connected to the usage of createGraphics() - as soon as I am not using this method, the errors are gone.

Kinrany commented 4 years ago

Hi, thanks for the report and the kind words :)

I'd like to investigate. Do you by any chance already have a repo I could use to reproduce this?

icarito commented 4 years ago

Hi Nice lib, I hadn't seen it when I started my project! I'm facing the same problem, I believe it is some kind of problem with removing and re-creating the canvas when createGraphics has been called. Some kind of problem with _registeredMethods.

I'm using createGraphics in my default sketch (to integrate with other rendering lib) and now I can't "reset" my sketch. The exact same error as described above appears when you push "RESET" button in my project here: http://super-8.glitch.me/

Any hint will help! Thanks!

icarito commented 4 years ago

Hi, just a comment that I worked around my issue by NOT removing the p5 canvas, just resetting its state. But I still think this is a bug with p5.createGraphics. Thanks!

Kinrany commented 4 years ago

Hi icarito, this is super helpful, thanks :D

Kinrany commented 4 years ago

Oh, I cloned the repo and couldn't find any reference to vue-p5. It seems I misread your first comment, @icarito, and you never actually switched to using it, right?

Still, I'd like to find the problem and report it upstream. Do you by any chance remember a commit where RESET was still broken?

icarito commented 4 years ago

Yes the one commit before last, still had broken RESET, it should be the only one. Sorry I pushed after working around the issue last night! Merry xmas!

El mar, 24-12-2019 a las 07:26 -0800, Kinrany escribió:

Oh, I cloned the repo and couldn't find any reference to vue-p5. It seems I misread your first comment, @icarito, and you never actually switched to using it, right?

Still, I'd like to find the problem and report it upstream. Do you by any chance remember a commit where RESET was still broken?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

Kinrany commented 4 years ago

No problem, and I got it, thanks. Merry xmas :)

lorenzki commented 4 years ago

Sorry, I have been already in my xmas holidays when you both started to comment. I have no repo to reproduce this problem right now - but I could make one if it's still needed. And @Kinrany as far as I have understood you were talking about this being a native p5 error rather than a issue with your package?

icarito commented 4 years ago

Hi,

Yes indeed I ran into this error without using the vue-p5 package.

I have since reverted my workaround.

I noticed that this had something to do with scope, that is, in my case, it would trigger if I assigned the p5 instance mode to an object property ( this.p5 = p5(...) ), but not if I ommitted this assignment ( p5(...) ).

https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=&repository_ref=main&search=P5&project_id=15850336#L94

The callback already offers access to the canvas with the .canvas property so this solved it for me.

Hope it helps!

El mar, 07-01-2020 a las 04:09 -0800, lorenzki escribió:

Sorry, I have been already in my xmas holidays when you both started to commenting. I have no repo to reproduce this problem right now - but I could make one if it's still needed. And @Kinrany as far as I have understood you were talking about this being a native p5 error rather than a issue with your package?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

Kinrany commented 4 years ago

@lorenzki yeah, since @icarito had this error too without using vue-p5, it seems to be a problem with p5 itself.

I have no repo to reproduce this problem right now - but I could make one if it's still needed.

It would be helpful, yes! Though a repo is not exactly necessary: a code snippet that demonstrates the problem would be good enough.

Chappie74 commented 4 years ago

Any updates on this? I am currently running into the same problem using create graphics.

Kinrany commented 4 years ago

Hi! This is an upstream problem, and I haven't been able to pinpoint exactly why it happens. A small example that reproduces the problem would be very helpful.

Chappie74 commented 4 years ago

Hi there. Thanks for replying :) Here i've just attached the methods and data part of my component. https://gist.github.com/Chappie74/73115dc181e85fdeb5b8215e50c4bd71 The problem started occurring when I added in the line: this.canvas.secondary = sk.createGraphics( this.canvas.width, this.canvas.height )

The error occurs when I make changes in the IDE and it automatically builds and updates to the page. The canvas wouldn't render. To solve this I have to hit the refresh button and reload the page.

EDIT

Here is a gist to the full component. https://gist.github.com/Chappie74/0f25e30d6495aa3d6d487f5708d4e1ec

Kinrany commented 4 years ago

Thank you!

Chappie74 commented 4 years ago

Hey @Kinrany. Just an update. For some reason during development, I had to remove node modules and reinstall them. Now I am not seeing the error anymore. I am not sure if this was a direct cause of that or something else during development. But i strongly believe that reinstalling the node modules fixed the issue.

Kinrany commented 4 years ago

Interesting, thanks for the heads up! Perhaps it was caused by an outdated dependency. I'll need to at least check that vue-p5 works with, and expects the current versions of its deps.

Chappie74 commented 4 years ago

Hey @Kinrany. So it seems i've ran into this problem again. So in my current set up, I have vue routing with history enabled. I have a nested route which I use for my game. It works fine when I first route to the route with the canvas on it. But should I change to a different route in the nested routes, then route back to the one with the canvas on it, this error occurs. Unfortunately, I cannot share the project for you to use. I too am using createGraphics

Kinrany commented 4 years ago

Hmm, sounds like a lifecycle bug. Thanks again for the report!

wokalek-work commented 3 years ago

Same problem.

msencenb commented 2 years ago

I'm also running into this problem. Digging into core p5.js, the issues seems to be happening on this line:

  // Allows methods to be registered on an instance that
  // are instance-specific.
  this._registeredMethods = {};
  var methods = Object.getOwnPropertyNames(p5.prototype._registeredMethods);
  for(var i = 0; i < methods.length; i++) {
    var prop = methods[i];
    this._registeredMethods[prop] = p5.prototype._registeredMethods[prop].slice(); // <-- Here
  }

Seems like somehow one of these registeredMethods is not a type of String or Array, which is causing that slice to fail? I have not yet figured out how to get to the bottom of where the registered method is getting set though.

EDIT: Pointed to core.js not the fork the pr originally was merged from in example.

msencenb commented 2 years ago

More info (potential solution below!)

With my setup I basically have a flat js file that exports a P5 instance for each template 'sketch' I have for people to browse/use. That was effectively creating a p5 instance like so, and in that squareSketch setup method is where I am creating the graphics context.

export const simpleBorderSquare = (node) => {
  console.log(Object.getOwnPropertyNames(p5.prototype._registeredMethods));
  return new p5(squareSketch, node);
};

Previously, I had set up my Vue component to have the p5 instance as a reactive data property:

data() {
    return {
        p5Wrapper: null,
    }
}

When I'm logging the registeredMethods of the p5.prototype on the first initialization, you get the expected 4 valeus:

Array(4) [ "init", "pre", "post", "remove" ]

However, when I try to 'reset' the instance by re-initializing things you'll notice that registeredMethods has been polluted:

this.p5Wrapper = simpleBorderSquare(this.refs.$p5cavas);
Array(5) [ "init", "pre", "post", "remove", "_obj_"]

Turns out that obj is the Vue Observer which gets jammed in there because I had set it as a reactive property. At least on my setup, that is what was causing that error - .slice() does not work on the Observer because it's not a String or Array.

Solution

For me, all I did was pull out the p5Wrapper so that it was no longer reactive, like so:

  // This is a custom, non-reactive reference to the p5 wrapper so Vue doesn't pollute the P5 prototype
  // Access like this.$options.p5Wrapper
  p5Wrapper: null,
  data() {
    return {};
  },

Once that's done you can access it with this.$options.p5Wrapper. Verified working on Vue 2, not sure about Vue 3 since my project has not upgraded yet.

Like others, I was not actually using the vue-p5 wrapper for this so I don't know if it actually impacts this repository (maybe I should have just used this nice wrapper 😅). Thank you for letting us hijack an issue on here @Kinrany - this was the only thread I found on Google that was actually helpful with this issue!

Kinrany commented 2 years ago

You're welcome, haha. The wrapper is indeed so small that for larger projects it may very well be more useful as a hub for discussing the use of Vue and p5 together.

ada-ada-ada-art commented 1 year ago

@msencenb's solution also put me on the right path. But for me, the solution was a bit more cumbersome, since I had references to both p5 and multiple p5.Graphics references inside an array of objects.

It looked something like this before fix:

export default Vue.extend({
  data() {
    return {
      canvas:p5,
      graphicsObjects:[
        {
          gfx:p5.Graphics
        },
        {
          gfx:p5.Graphics
        }
      ]
    }
  }
})

In the end, I had to move all p5 references out of data(). I didn't add a custom non-reactive property to Vue, but instead just declared the variables outside of the Vue instance:

let canvas = p5
let graphicsObjects = [
  {
    gfx:p5.Graphics
  },
  {
    gfx:p5.Graphics
  }
]
export default Vue.extend({
  data() {
    return {}
  }
})