Slide 1

Slide 1 text

Livecoding in Javascript Jason Frame / @jaz303 Friday, 31 May 13

Slide 2

Slide 2 text

What is livecoding? By akirto. http://www.flickr.com/photos/30132612@N00/3840200923/in/photostream Friday, 31 May 13

Slide 3

Slide 3 text

Performance-Oriented Friday, 31 May 13

Slide 4

Slide 4 text

Node-based Friday, 31 May 13

Slide 5

Slide 5 text

Microworlds Paper - “Twenty Reasons Why You Should Use Boxer (Instead of Logo)” Andrea A. diSessa Friday, 31 May 13

Slide 6

Slide 6 text

Smalltalk, Self Paper - “The Early History of Smalltalk” Alan C. Kay Friday, 31 May 13

Slide 7

Slide 7 text

Why livecode? Friday, 31 May 13

Slide 8

Slide 8 text

Why Javascript? Friday, 31 May 13

Slide 9

Slide 9 text

Why Javascript? • Flexible language • Ecosystem - browser + node.js = node- webkit • Single threaded • Event loop Friday, 31 May 13

Slide 10

Slide 10 text

Why Javascript? Describing Live programming using program transformations and a callstack explicit interpreter Olov Johansson Friday, 31 May 13

Slide 11

Slide 11 text

Domain-Specific Livecoding • Generalised tools can be complex • May also make unacceptable performance/ timing trade-offs • Evolve tools with your application Friday, 31 May 13

Slide 12

Slide 12 text

Demo Time Friday, 31 May 13

Slide 13

Slide 13 text

Friday, 31 May 13

Slide 14

Slide 14 text

Implementation Strategies Friday, 31 May 13

Slide 15

Slide 15 text

Implementation Strategies eval() is evil Friday, 31 May 13

Slide 16

Slide 16 text

Implementation Strategies eval() is evil Friday, 31 May 13

Slide 17

Slide 17 text

Implementation Strategies • Private State • Variable Injection • “Globals” Preservation • Internal eval() • Blueprints • Snapshot • Clocksources Friday, 31 May 13

Slide 18

Slide 18 text

Private State Prevent pollution of global namespace Friday, 31 May 13

Slide 19

Slide 19 text

Private State function setup() { position = {x: 10, y: 20}; velocity = {x: 1, y: 1}; } function loop() { position.x += velocity.x; position.y += velocity.y; } Friday, 31 May 13

Slide 20

Slide 20 text

Private State (function() { “use strict”; var position; var velocity; function setup() { position = {x: 10, y: 20}; velocity = {x: 1, y: 1}; } function loop() { position.x += velocity.x; position.y += velocity.y; } })(); Friday, 31 May 13

Slide 21

Slide 21 text

Private State (function() { “use strict”; var position; var velocity; function setup() { position = {x: 10, y: 20}; velocity = {x: 1, y: 1}; } function loop() { position.x += velocity.x; position.y += velocity.y; } return { setup: setup, loop: loop }; })(); Friday, 31 May 13

Slide 22

Slide 22 text

Variable Injection Provide objects to user-code Friday, 31 May 13

Slide 23

Slide 23 text

Variable Injection function loop() { car.drawAt(0,0,50,50) } // ... // ... // ... Friday, 31 May 13

Slide 24

Slide 24 text

Variable Injection // Generate method signature from defined // objects (function(car, trafficLights, background) { // Paste user code here function loop() { car.drawAt(0,0,50,50) } // ... // ... // ... }).apply(null, exposedObjects); Friday, 31 May 13

Slide 25

Slide 25 text

“Globals” Preservation Persist global values between code reloads Friday, 31 May 13

Slide 26

Slide 26 text

“Globals” Preservation var carX = 0; var carY = 0; var speed = 5; function loop() { carY += speed; draw(); } Friday, 31 May 13

Slide 27

Slide 27 text

“Globals” Preservation var carX = 0; var carY = 0; var speed = 5; function loop() { carY += speed; draw(); } Friday, 31 May 13

Slide 28

Slide 28 text

“Globals” Preservation (function() { "use strict"; var carX = 0; var carY = 0; var speed = 5; function loop() { carY += speed; draw(); } return { loop: loop, getVars: function() { return {carX: carX, carY: carY, speed: speed}; }, setVars: function(vars) { carX = vars.carX; carY = vars.carY; speed = vars.speed; } }; })(); Friday, 31 May 13

Slide 29

Slide 29 text

Internal eval() Provide external (e.g. console) access to private state Friday, 31 May 13

Slide 30

Slide 30 text

Internal eval() var car = {x: 20, y: 20} var lightState = “red-amber” function setup() { // ... } function loop() { // ... } Friday, 31 May 13

Slide 31

Slide 31 text

Internal eval() (function() { "use strict"; var car = {x: 20, y: 20} var lightState = “red-amber” function setup() { // ... } function loop() { // ... } })(); Friday, 31 May 13

Slide 32

Slide 32 text

Internal eval() (function() { "use strict"; var car = {x: 20, y: 20} var lightState = “red-amber” function setup() { // ... } function loop() { // ... } function evaluate(code) { return eval(code); } return { __eval__: evaluate } })(); Friday, 31 May 13

Slide 33

Slide 33 text

Blueprints Augment a supplied object with user-code Friday, 31 May 13

Slide 34

Slide 34 text

Blueprints // Inside engine var blueprint = new SystemBlueprint(); blueprint.id = oldSystem.id; blueprint.enabled = oldSystem.enabled; blueprint.update = function() { /* default impl */ } USERCODE = ‘(function(system) { // augment blueprint system.title = “foo”; system.update = function() { ... } })’; // Compile code systemBuilder = eval(USERCODE); systemBuilder(blueprint); // inspect user’s refinements to blueprint and // setup accordingly Friday, 31 May 13

Slide 35

Slide 35 text

Snapshots Save and restore entire application state Friday, 31 May 13

Slide 36

Slide 36 text

Snapshots system.snapshot = function() { return { entities: Object.keys(this.entities), lastShotTime: this.lastShotTime } } system.restore = function(snapshot) { var self = this; this.entities = {}; snapshot.entities.forEach(function(eid) { self.entities[eid] = self.world.getEntityById(eid); } this.lastShotTime = snapshot.lastShotTime; } Friday, 31 May 13

Slide 37

Slide 37 text

Snapshots function updateSystem(registry, systemId, newSystem) { var existingSystem = registry.getSystemById(systemId); var snapshot = existingSystem.snapshot(); try { newSystem.restore(snapshot); registry.setSystem(systemId, newSystem); } catch (e) { // Incompatible snapshot - restart app? } } Friday, 31 May 13

Slide 38

Slide 38 text

Clocksources Provide a consistent view of time when loading snapshots Friday, 31 May 13

Slide 39

Slide 39 text

Clocksources Date.now() Friday, 31 May 13

Slide 40

Slide 40 text

Clocksources Date.now() function Clock() { this.time = 0; this.lastDelta = null; } Clock.prototype.tick = function(delta) { this.time += delta; this.lastDelta = delta; } function tick() { var wallclockDelta = Date.now() - lastTick; clock.tick(wallclockDelta); } Friday, 31 May 13

Slide 41

Slide 41 text

Escaping the Walled Garden Friday, 31 May 13

Slide 42

Slide 42 text

Escaping the Walled Garden Friday, 31 May 13

Slide 43

Slide 43 text

Escaping the Walled Garden Friday, 31 May 13

Slide 44

Slide 44 text

Demo Time Friday, 31 May 13