geo-at-github/hotswap.js

Prototype functions

Closed this issue · 6 comments

Hello. The code seams great, really easy to use,

Sorry, the code before was wrong.
Your code works perfectly, but I can't delete the issue... so I will comment on it.

Sometimes when you change a prototype, it updates all it's instance, and sometimes it doesn't. I have no idea why.

In my experience it sometimes takes a few frames until the js is replaced which might cause weird behaviour for automated or looping events.

If there is an explicit assignment of the prototpye function to an object then JS will copy the function by value creating an in-memory copy of the function. Those copies will never be updated. I have created a JsFiddle to illustrate this problem: http://jsfiddle.net/2Aud2/3/.

Concerning the unreliability of the JS prototype updates it would be nice if you could isolate the faulty behaviour and create a jsFiddle example to investigate.

Ok. After many hours under the road, I think I have understood it.

It's weirder than your example (which was pretty clear). I think that it has to do with some sort of scope.

For all the examples I always updated from the GUI. (Main reason that I couldn't use jsFiddle)

Fist, if a function is inside of another function it isn't updated. Example: http://jsfiddle.net/5GVYs/
Makes sense so far, the function exists only in the memory of that object, the object doesn't have any relationships and is never referenced, so it makes sense that JS isn't reading the same file all the time.

If you take that function and place it outside (I think that would make it public) it is updated.
http://jsfiddle.net/k75SZ/

Now for the weird part. Back to the topic of updating all instances when a prototype is modified. A private variables dies with the scope so it doesn't make sense to update them, so I tested public variables and object properties.

Starting with public variables. Weird thing number one: you need to create your object outside of the function. Example: http://jsfiddle.net/V283u/
That doesn't work.

But this does work: http://jsfiddle.net/9fuP2/

Weird thing number 2, updating objects properties, the type of object you are referencing need to be in another file... I really don't understand this one.
Example: http://jsfiddle.net/z6V9h/
If all the Entity thingies are in another file, it gets updated properly. But if it's in the same file, it isn't.

That were my experiments. I have no idea how to test them with jsFiddle, so here is the code I used for all tests: http://jsfiddle.net/WKzHe/

Thank you for the test scenarios. I have added a function-in-function test which I think illustrates the problem ( https://github.com/geo-at-github/hotswap.js/tree/master/dev/tests/function-in-function ).

You will have to make the code reload-able (renew all in-memory copies and function callbacks). I did this in the test by calling main() again after each refresh.

As for "Weird thing number 2" - I didn´t have time to investigate this in detail but I think it is related to the same issue.

It works with the interval, but it doesn't work with a requestAnimationUpdate. Well... actually it works, but a new function is created, and the old plus the new function are called. So with every change you ran your code 1 more time. http://jsbin.com/ralufexa/1/edit

So it looks that you actually can't update a function inside a function, the only way is updating the main function (external). And for doing that you need to destroy the old one and call it again.
No very friendly with a game loop, but not really a deal breaker, the game loop could be a global function on it's own and that will solve it.

In object oriented terms: you can't update the methods of an instance without reloading the full instance... or you just can't... what you actually do is create another instance with the new method and never use the old instance again.

Actually that isn't a real issue. You weren't supposed to do it in the first place.

Don't worry to much about my first post. You can update global functions and prototype methods, which is actually all you need.

OH! Now I understand the problem with weird thing number 1. Hotswap don't just reload a script, it execute it as well, and when the script it's executed again, the public variable is recreated/reloaded/cleaned, so the reference is lost.

So what hotswap can actually do is: run a script (by reloading a script than contains code) and upload public functions so when they are called again, the code is changed. That includes updating objects and the prototypes of the new created object.

And because js is cool, if you change a prototype it affects all it's instances.

Yes, hotswap reloads the whole .js file which is then executed automatically by the browser just like any other regular .js file.

"requestAnimationUpdate" should work just like the "setInterval" in the example. You will have to save the interval-id and use window.cancelAnimationFrame() after each refresh. Just swap "setInterval" and "clearInterval" with "requestAnimationUpdate" and "cancelAnimationFrame" (+ the weirdness of re-registering "requestAnimationUpdate" on every call) and you should be fine.

I will close the ticket now.
Feel free to reopen it if necessary and thank you for your interest in hotswap.js.

Thank you for creating this amazing tool.
You save me countless hours.