Transcript
Page 1: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

PROXIES BEFORE

PROXIES: THE HIDDEN

GEMS OF JAVASCRIPT AOP

Page 2: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

1 - SHOES

Page 3: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

2 - GLOVES

Page 4: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

3 - JUMPER

Page 5: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

4 – COAT TAILS

Page 6: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

SCARLETJS

The simple fast JavaScript interceptor.

Page 7: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

SCARLETJS

• API fluent interface

• Readability

• Performance

• Use of Core features

• Lack of ability to use common proxies

• Challenge

• And to have a little fun

Page 8: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

WHAT IS A PROXY?

Page 9: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var awesmeoThing = function(){

}

Page 10: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms

Page 11: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var awesomeoThing = function(x,y,z){

var startTime = new Date();

var endTime = new Date();

console.log(‘called awesomeoThing‘ + new Date()

+ ’ with params:’

+ [x,y,z]

+ ’ executed in:’

+ endTime-startTime);

}

Page 12: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 13: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Public class AnyClass{

Public void awesmeoThing(int x,int y,int z){

}

}

Page 14: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

@Component

@Aspect

public class MyLogger{

@Around("execution(* com.my.messaging..*.*(..))")

public Object logAfterMethod(ProceedingJoinPoint joinPoint) throws Throwable {

Logger log = Logger.getLogger(joinPoint.getTarget().getClass());

StopWatch stopWatch = new StopWatch();

stopWatch.start();

Object retVal = joinPoint.proceed();

stopWatch.stop();

….

System.out.println(“called: “

+ joinPoint.getTarget().getClass().getName()

+ “ with args: “

+ args

+ “executed in: “

+ stopWatch.getTotalTimeMillis());

}

}

Page 15: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

OK…SO WHAT ARE

PROXIES?

And what happened to the JavaScript?

Page 16: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Var wrapper = function(){

var startTime = new Date();

var result = awesmeoThing();

var endTime = new Date();

console.log(‘called awesomeoThing‘

+ new Date()

+ ’ with params:’

+ [x,y,z]

+ ’ executed in:’

+ endTime-startTime);

return result;

}

Page 17: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var wrapper = function(){

var startTime = new Date();

var result = awesmeoThing();

var endTime = new Date();

console.log(‘called awesomeoThing‘

+ new Date()

+ ’ with params:’

+ x+y+z

+ ’ executed in:’

+ endTime-startTime);

return result;

}

var awesomeoThing = function(x,y,z){

var startTime = new Date();

var endTime = new Date();

console.log(‘called awesomeoThing‘

+ new Date()

+ ’ with params:’

+ x+y+z

+ ’ executed in:’

+ endTime-startTime);

}

Page 18: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 19: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

WHAT’S OUT THERE

TODAY?

• Hooker by Ben Alman (Cowboy) (Author and

main contributor of grunt)

• “Monkey-Patch(hook) functions for debugging

and stuff” – Github Readme

• Hooks by Brian Noguchi(bnoguchi)

• “Add pre and post middleware hooks to your

JavaScript methods.”

Page 20: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

HOOKER

hooker.hook(Math, "max", function() {

console.log(arguments.length + " arguments passed");

});

// logs: "3 arguments passed"

Math.max(5, 6, 7)

Page 21: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

HOOKJS

• create an instance of the thing

var instance = new awesemoThing();

• assign each member of the hooks implementation into the object

for(var k in hooks){

Instance[k] = hooks[k];

}

• Implement a method to implement before underlying method is called:

instance.pre(‘method’,function(next){

})

• Implement a post method to get called after the underlying method is called:

Instance.post(‘method’,function(next){

})

Page 22: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

EXISTING

IMPLEMENTATIONS

• Imbedded in popular projects

• We want to do it

• API and Module design

Page 23: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 24: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

API FLUENT

INTERFACE

myFunction.do(<SOMETHING>)

.do(<SOMETHING_ELSE>)

.andDoMore();

Page 25: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

READABILITY

Page 26: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

PERFORMANCE

• Lo-Dash - John-David Dalton

• Best of breed - https://github.com/beastiejs

Page 27: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

USE OF CORE

FEATURES

• No pre and post methods. Use real events

Page 28: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

LACK OF ABILITY TO USE

COMMON PROXIES

• Easily be able to pull down and

use a logger, security module, etc

Page 29: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

CHALLENGE

Page 30: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

AND TO HAVE A LITTLE

FUN…TO MAKE MY CODE

PURR

Page 31: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var purr = scarlet.plugins.purr;

purr.when(Math,'min').play();

Math.min(1,2,3);

Page 32: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

SCARLETJS -

THE PROJECT

Page 33: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 34: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 35: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

TESTING

• Tools Used

• Mocha

• Builders

ScarletBuilder.forInstance(<AnyInstance>)

ScarletBuilder.forProperty(<AnyProperty>)

.withInterceptors(<ArrayOfInterceptors>);

ScarletBuilder.forMethod(<AnyMethod>)

.withParameters(<AnyParams>)

.withEvents(<AnyEvents>)

.Assert();

Page 36: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 37: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

MAKING IT EASY

• Intercept a function, object, or property

• Define event listeners for before and after the intercepted function had been called

• Define multiple functions to do the interception

• Being able to chain method calls together and have a fluent interface

Page 38: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Scarlet.intercept(<ANYTHING>)

Page 39: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Scarlet.intercept(<ANYTHING>)

.on(‘before’,<BEFORE_FUNC>)

.on(‘after’,<AFTER_FUNC>)

.on(‘done’,<DONE_FUNC>)

.on(‘error’,<ERROR_FUNC>);

Page 40: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Scarlet.intercept(<ANYFUNCTION>)

.using(<INTERCEPTOR_FUNC)

Page 41: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Scarlet.intercept(<ANYFUNCTION>)

.using(function(proceed){

//…BEFORE

proceed();

//…AFTER

});

Page 42: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Scarlet.intercept(<ANYFUNCTION>)

.using(function(info, proceed){

//…BEFORE

proceed();

//…AFTER

});

Page 43: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var someProxy = Scarlet.intercept(<ANYFUNCTION>)

.using(<INTERCEPTOR_FUNCTION>)

.proxy();

Page 44: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Var awesemeoThing = function(){}

var someProxy = Scarlet.intercept(awesemeoThing)

.using(function(info, proceed){

var startTime = new Date();

var result = proceed();

var endTime = new Date();

console.log(‘called ‘ +info.methodName

+ new Date()

+ ’ with params:’

+ [x,y,z]

+ ’ executed in:’

+ endTime-startTime);

})

.proxy();

Page 45: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

PERFORMANCE

Page 46: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

PLUGINS

• Scarlet Passport

• Scarlet-winston

• Scarlet-ioc

• Scarlet-init

Page 47: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var requestListener = scarletPassport

.scarletPassport

.authenticate('local',

{},

requestListener)

Page 48: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

scarletWinston.bindTo(Math,'min');

Math.min(1,2,3);

//->info: [Mon Sep 02 2013 00:49:58 GMT+0100 (BST)] calling -

Object::min(1,2,3)

//->info: [Mon Sep 02 2013 00:49:58 GMT+0100 (BST)]

Object::min(1,2,3) - returned:1 - execution time(0:0:0.0)

Page 49: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

function MyObjectB(myObjectA){

};

scarlet.plugins.ioc

.register("myObjectA", MyObjectA)

.register("myObjectB", MyObjectB);

var myObjectB = scarlet

.plugins

.ioc

.resolve("myObjectB");

myObjectB.anyMethod();

Page 50: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 51: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

ES6 - PROXIES

”A proxy object is an exotic object whose essential

internal methods are partially implemented using ECMAScript

code” – ES6 Draft October 2014

Page 52: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var awesemeoFunction = function(){…};

var proxiedObject = new Proxy(awesemeoFunction,{

apply: function(target, receiver, args){

var startTime = new Date();

var result = target(args);

var endTime = new Date();

console.log(‘called awesomeThing‘ + new Date()

+ ’ with params:’

+ args

+ ’ executed in:’

+ endTime-startTime);

return result;

}

});

Page 53: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var awesemeoThing= {};

var proxiedThing = new Proxy(awesemeoThing,{

get: function(target, name){

console.log("In Get Proxy");

return target[name];

}

});

var x = proxiedThing.any;

Page 54: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var awesemeoThing= {};

var proxiedThing = new Proxy(awesemeoThing,{

set: function(target, name, value){

console.log("In Set Proxy");

target[name] = value;

}

});

proxiedThing.any = 'thing';

Page 55: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

NODE.JS PROXIES

• Proxies can be enabled using the following commands:

• $ node –harmony-proxies

• $ node --harmony

Page 56: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Page 57: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

HARMONY-REFLECT

• Shim so that the current draft implementation of proxies can be used https://github.com/tvcutsem/harmony-reflect

1. Install the module:

• npm install harmony-reflect

2. Require at the top of your js file:

• require(‘harmony-reflect);

3. Run node in harmony mode:

• $ node --harmony

Page 58: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

FIREFOX

• Available in versions 18+

Page 59: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

PROXIES IN USE –

NEGATIVE ARRAY

Page 60: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var negativeArray = require('negative-array');

var unicorn = negativeArray(['pony',

'cake',

'rainbow']);

console.log(unicorn[-1]);

Page 61: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

module.exports = function (arr) {

return new Proxy(arr, {

get: function (target, name) {

var i = +name;

return target[i < 0 ?

target.length + i :

i];

},

}

Page 62: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

ANNOTATIONS

• Traceur – Converts ES6 to ES5 runnable code

• https://github.com/google/traceur-compiler

• Install through npm

• Npm install traceur

• Allows for annotations to be used with the following flags:

• traceur <ANY_FILE> --annotations true

Page 63: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

@AnyAnnotation

function simpleFunction () {

return 'any';

}

Page 64: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var AnyAnnotation = function() {};

function simpleFunction() {

return 'any';

}

Object.defineProperty(simpleFunction,

"annotations",

{

get: function() {

return [new AnyAnnotation];

}

});

Page 65: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

Console.log(simpleFunction.annotations)

//-> [function AnyAnnotation(){}]

Page 66: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

LOGGER

ANNOTATIONS

@Logger

function simpleFunction () {

return 'any';

}

Page 67: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var Logger = function(){

return function( target, receiver, args) {

var startTime = new Date();

var result = target(args);

var endTime = new Date();

console.log(‘called ‘ + target.name + new Date()

+ ’ with params:’

+ args

+ ’ executed in:’

+ endTime-startTime);

return result;

};

};

Page 68: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

var createProxy = function(anyFunction){

return new Proxy(anyFunction,

{

apply : anyFunction. annotations[0]

});

};

simpleFunction = createProxy(simpleFunction);

simpleFunction();

Page 69: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

called simpleFunction Thu Oct 23 2014

23:33:02 GMT+0100 (GMT Daylight Time)

with params: executed in:0

Page 70: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

THE FUTURE FOR

SCARLETJS

Page 71: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

THANK YOU

• @timchaplin

• https://github.com/tjchaplin

Page 72: Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP

REFERENCES

• http://soft.vub.ac.be/~tvcutsem/invokedynamic/proxies_tutorial

• https://brendaneich.com/2012/10/harmony-of-dreams-come-true/

• http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts

• http://dailyjs.com/2013/11/15/negative-array/

• https://github.com/sindresorhus/negative-array/blob/master/package.json

• https://github.com/tvcutsem/proxy-handlers

• https://github.com/JustinDrake/node-es6-examples#proxies