This page documents research results for building out live JavaScript development. We're starting with work [using the APIs built into Chrome](https://trello.com/card/2-research-chrome-implementation-for-live-javascript/4f90a6d98f77505d7940ce88/837).
## Issues with Feature Behavior ##
* Using the [TodoMVC](http://todomvc.com) jquery example
* The footer blinks when the ScriptAgent is turned on (even when no edits have been made to the script). Even more noticeable with the Backbone example
* The Live Development icon looks like it's turned off
* Why does reload take a long time when I save a .js file vs. when I save the HTML file?
* Adding a method to the object does not work (can't find the method)
* Adding a function to the closure does not work (can't find the function)
* further, the error displayed on the console didn't even reflect the full name of the function it couldn't find. It's as if the engine stopped updating.
* Just tried this again with a function that already existed... and it chopped off the last character of the function name both times!
* needs more looking:
* moved some functionality into a function
* commented out the call to that function
* alert call showed that it was still calling that function
* changing a variable's value set in a closure does not work (`var foo = 1000;` changed to `var foo = 10;`)
* deleting a line that calls a function seems to stop the updating sometimes
* Using a [canvas demo](https://github.com/chrislongo/html5-canvas-demo)
* The framerate does *not* appear to be affected by having the ScriptAgent loaded (I had a theory about the blinking in TodoMVC. Turned out to be false)
* not surprisingly, making a change to `initPalette` live has no effect
* changing `smooth`, on the other hand, works fine
* changing a script in the HTML page has no effect
* adding code outside of a function block in the script file has no effect
# Live JS With Chrome: What You Can/Can't Do #
There are specific things that you can and can't do reliably when modifying JavaScript code using Chrome's debugging features. I'll run through specific cases to describe how they work/don't work. First, a couple of high-level notes:
* It does not appear that you can modify JS that is in the HTML file. This is not tested at the API level, but it does not work within the Chrome Dev Tools UI.
* Since JavaScript is an imperative language, the only changes that can reasonably be expected to have an effect are changes to functions that will be called again.
* When doing Live JavaScript editing, the live editing icon has the disconnected appearance.
* Using TodoMVC as an example, the footer that displays the number of todo items tends to blink in a way that it does not when you're not doing live JS editing.
The following sections will describe specific kinds of cases and how they perform.
## The Setup ##
Use the `dangoor/live-js-research` branch of Brackets. All this branch does is turn on the live JS feature.
This is the simplest case. Imagine the following code attached to a click handler:
```javascript
functionlogIt(){
log("global message");
}
```
You can modify that line of code, add additional lines, add code that creates local variables, access global variables. In short, functions of this sort can be modified without difficulty.
## Top-Level Function with a Closure ##
```javascript
functionlogIt(){
vari=1;
log("global message "+i++);
setTimeout(function (){
log("timed message "+i);
},1000);
}
```
As with the case above, this one appears to work just fine. In fact, this case was derived from the previous one without reloading, so adding a closure is fine.
## Object Construction ##
```javascript
functionThing(name){
this.name=name;
}
functionlogIt(){
vart=newThing("Alfred");
setTimeout(function (){
log("timed message "+t.name);
},15);
}
```
In my file, I already had the `Thing` constructor above in the same file as the `logIt` function from the previous case. I was able to modify `logIt` into the form above without reloading.
I just also confirmed that random whitespace changes between these functions has no effect.
We now reach our first unexpected behavior. I altered the code to appear as below:
```javascript
functionThing(name,age){
this.name=name;
this.age=age;
}
functionlogIt(){
vart=newThing("Alfredbot",21);
setTimeout(function (){
log(t.name+" is "+t.age+" years old");
},15);
}
```
When run, `logIt` displays "Alfredbot is undefined years old". If I reload the page (just by saving the JS file), this works as expected. I can alter the age provided in logIt. I also changed the `Thing` constructor to set `this.age = age * 2;`, and that also worked. I added `this.doubleAge = age * 2;` and changed `logIt` to display `t.doubleAge` instead of `t.age`, and that also worked.
I was able to change the `Thing` constructor's arguments to be `n, a` and that change also behaved just fine.
Also modify `logIt` to pass in a num argument. I observed in making these changes that:
* Adding the argument did not work (as expected from the previous case)
* Removing the added code did not put the `log` function back into a state where live changes could be made
* Changes could still be made to `logIt`, even though `log` would no longer accept changes
## Removing an Argument ##
Save the file with the modified `log` function above. After the reload, it should log with the `num` argument just fine. Remove the `num` argument and the `+ num ` in the `log` function.
**Removing a function argument also seems problematic**
## Renaming a Function ##
Put the `log` function back to its original state. Rename the function to `logger`, but don't change the call to it from the `logIt` function. Clicking on Logger on the test page still logs, despite the fact that the name is theoretically different.
**Renaming a function has no effect**
## Adding a Function ##
Reload the page and then add a function called `doubleIt` and call that function from `logIt`. Here's the code we end up with:
```javascript
functiondoubleIt(a,b){
return (a+b)*2;
}
functionlogIt(){
vart=newThing("Alfredbot",22,"Sword");
log(t.name+" is "+t.doubleAge+" years old and his weapon of choice is "+t.np+""+doubleIt(4,1));
}
```
Not surprisingly, `logIt` is now broken because it does not see the `doubleIt` function. This is not a surprise, because the `doubleIt` function declaration has not been executed.
**You cannot add a new function in a scope that has already been executed**
## Adding a Function by Executing Another ##
For the next cases, we'll start walking through prototype manipulation. We'll redo the setup to give us another function we can execute to work with.
Be sure to reload after these changes have been made. In `resetThing`, add the `doubleIt` function to `window` (without a reload):
```javascript
functionresetThing(){
log("resetting");
window.doubleIt=function(a,b){
return (a+b)*2;
}
}
```
and call `doubleIt` from `logIt`:
```javascript
log(t.name+" is "+t.doubleAge+" years old and his weapon of choice is "+t.np+""+doubleIt(4,5));
```
Click Reset Thing on the page, then click Logger. You'll see that doubleIt was successfully added to the page.
## Modifying a Function by Re-Running Code ##
Changing the `doubleIt` function works just fine, as you'd expect. What if we want to change the function signature? Add a `c` parameter to `doubleIt`, and also add a third number to `logIt`.
`doubleIt`'s declaration now looks like this:
```javascript
window.doubleIt = function(a, b, c) {
return (a + b + c) * 2;
}
```
Click Reset Thing and then Logger. The new definition of `doubleIt` is in place.
## Adding to an Object Prototype ##
Remove `doubleIt` and the reference to it in `logIt`. Reload the page.
Click Reset Thing, Logger. Note that it doesn't log because it can't find `t.doubleAge`. Reload and confirm that `logIt` can then find `t.doubleAge`. Once you've done this, you can change `doubleAge` and it works fine.
**Adding to an object prototype doesn't work!**
## Adding to an Object Prototype, Part 2 ##
Add this to the `resetThing` function and change `logIt` to call this instead of `doubleAge`:
```javascript
Thing.prototype.tripleAge = function() {
return this.age * 3;
}
```
Click Reset/Logger. Note that adding *this* function worked where the previous one did not.
**You can add to an object prototype in a function where you previously added to it**
## Adding to a New Prototype ##
Let's see how differently it behaves when you use a different style of manipulating an object prototype:
```javascript
function Thing(name, age) {
this.name = name;
this.age = age;
}
var startTime = new Date().getTime();
function log(message) {
var difference = parseInt((new Date().getTime() - startTime) / 1000);