SlideShare a Scribd company logo
P 
ROXIES BEFORE 
PROXIES: THE HIDDEN 
GEMS OF JAVASCRIPT AOP
1 - SHOES
2 - GLOVES
3 - JUMPER
4 – COAT TAILS
SCARLETJS 
The simple fast JavaScript interceptor.
SCARLETJS 
• API fluent interface 
• Readability 
• Performance 
• Use of Core features 
• Lack of ability to use common proxies 
• Challenge 
• And to have a little fun
WHAT IS A PROXY?
var awesmeoThing = function(){ 
… 
}
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
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); 
… 
}
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
Public class AnyClass{ 
Public void awesmeoThing(int x,int y,int z){ 
… 
} 
}
@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()); 
} 
}
OK…SO WHAT ARE 
PROXIES? 
And what happened to the JavaScript?
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 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); 
… 
}
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.”
HOOKER 
hooker.hook(Math, "max", function() { 
console.log(arguments.length + " arguments passed"); 
}); 
// logs: "3 arguments passed" 
Math.max(5, 6, 7)
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){ 
})
EXISTING 
IMPLEMENTATIONS 
• Imbedded in popular projects 
• We want to do it 
• API and Module design
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
API FLUENT 
INTERFACE 
myFunction.do(<SOMETHING>) 
.do(<SOMETHING_ELSE>) 
.andDoMore();
READABILITY
PERFORMANCE 
• Lo-Dash - John-David Dalton 
• Best of breed - https://github.com/beastiejs
USE OF CORE 
FEATURES 
• No pre and post methods. Use real events
LACK OF ABILITY TO USE 
COMMON PROXIES 
• Easily be able to pull down and 
use a logger, security module, etc
CHALLENGE
AND TO HAVE A LITTLE 
FUN…TO MAKE MY CODE 
PURR
var purr = scarlet.plugins.purr; 
purr.when(Math,'min').play(); 
Math.min(1,2,3);
SCARLETJS - 
THE PROJECT
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript AOP
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();
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
Scarlet.intercept(<ANYTHING>)
Scarlet.intercept(<ANYTHING>) 
.on(‘before’,<BEFORE_FUNC>) 
.on(‘after’,<AFTER_FUNC>) 
.on(‘done’,<DONE_FUNC>) 
.on(‘error’,<ERROR_FUNC>);
Scarlet.intercept(<ANYFUNCTION>) 
.using(<INTERCEPTOR_FUNC)
Scarlet.intercept(<ANYFUNCTION>) 
.using(function(proceed){ 
//…BEFORE 
proceed(); 
//…AFTER 
});
Scarlet.intercept(<ANYFUNCTION>) 
.using(function(info, proceed){ 
//…BEFORE 
proceed(); 
//…AFTER 
});
var someProxy = Scarlet.intercept(<ANYFUNCTION>) 
.using(<INTERCEPTOR_FUNCTION>) 
.proxy();
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();
PERFORMANCE
PLUGINS 
• Scarlet Passport 
• Scarlet-winston 
• Scarlet-ioc 
• Scarlet-init
var requestListener = scarletPassport 
.scarletPassport 
.authenticate('local', 
{}, 
requestListener)
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)
function MyObjectB(myObjectA){ 
}; 
scarlet.plugins.ioc 
.register("myObjectA", MyObjectA) 
.register("myObjectB", MyObjectB); 
var myObjectB = scarlet 
.plugins 
.ioc 
.resolve("myObjectB"); 
myObjectB.anyMethod();
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
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; 
} 
});
var awesemeoThing= {}; 
var proxiedThing = new Proxy(awesemeoThing,{ 
get: function(target, name){ 
console.log("In Get Proxy"); 
return target[name]; 
} 
}); 
var x = proxiedThing.any;
var awesemeoThing= {}; 
var proxiedThing = new Proxy(awesemeoThing,{ 
set: function(target, name, value){ 
console.log("In Set Proxy"); 
target[name] = value; 
} 
}); 
proxiedThing.any = 'thing';
NODE.JS PROXIES 
• Proxies can be enabled using the following commands: 
• $ node –harmony-proxies 
• $ node --harmony
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
FIREFOX 
• Available in versions 18+
PROXIES IN USE – 
NEGATIVE ARRAY
var negativeArray = require('negative-array'); 
var unicorn = negativeArray(['pony', 
'cake', 
'rainbow']); 
console.log(unicorn[-1]);
module.exports = function (arr) { 
… 
return new Proxy(arr, { 
get: function (target, name) { 
var i = +name; 
return target[i < 0 ? 
target.length + i : 
i]; 
}, 
}
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
@AnyAnnotation 
function simpleFunction () { 
return 'any'; 
}
… 
var AnyAnnotation = function() {}; 
function simpleFunction() { 
return 'any'; 
} 
Object.defineProperty(simpleFunction, 
"annotations", 
{ 
get: function() { 
return [new AnyAnnotation]; 
} 
});
Console.log(simpleFunction.annotations) 
//-> [function AnyAnnotation(){}]
LOGGER 
ANNOTATIONS 
@Logger 
function simpleFunction () { 
return 'any'; 
}
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; 
}; 
};
var createProxy = function(anyFunction){ 
return new Proxy(anyFunction, 
{ 
apply : anyFunction. 
annotations[0] 
}); 
}; 
simpleFunction = createProxy(simpleFunction); 
simpleFunction();
called simpleFunction Thu Oct 23 2014 
23:33:02 GMT+0100 (GMT Daylight Time) 
with params: executed in:0
THE FUTURE FOR 
SCARLETJS
THANK YOU 
• @timchaplin 
• https://github.com/tjchaplin
REFERENCES 
• http://soft.vub.ac.be/~tvcutsem/invokedynamic/proxies_tut 
orial 
• https://brendaneich.com/2012/10/harmony-of-dreams-come- 
true/ 
• http://wiki.ecmascript.org/doku.php?id=harmony:specifica 
tion_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

More Related Content

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

  • 1. P ROXIES BEFORE PROXIES: THE HIDDEN GEMS OF JAVASCRIPT AOP
  • 5. 4 – COAT TAILS
  • 6. SCARLETJS The simple fast JavaScript interceptor.
  • 7. SCARLETJS • API fluent interface • Readability • Performance • Use of Core features • Lack of ability to use common proxies • Challenge • And to have a little fun
  • 8. WHAT IS A PROXY?
  • 9. var awesmeoThing = function(){ … }
  • 10. 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
  • 11. 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); … }
  • 13. Public class AnyClass{ Public void awesmeoThing(int x,int y,int z){ … } }
  • 14. @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()); } }
  • 15. OK…SO WHAT ARE PROXIES? And what happened to the JavaScript?
  • 16. 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; }
  • 17. 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); … }
  • 19. 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.”
  • 20. HOOKER hooker.hook(Math, "max", function() { console.log(arguments.length + " arguments passed"); }); // logs: "3 arguments passed" Math.max(5, 6, 7)
  • 21. 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){ })
  • 22. EXISTING IMPLEMENTATIONS • Imbedded in popular projects • We want to do it • API and Module design
  • 24. API FLUENT INTERFACE myFunction.do(<SOMETHING>) .do(<SOMETHING_ELSE>) .andDoMore();
  • 26. PERFORMANCE • Lo-Dash - John-David Dalton • Best of breed - https://github.com/beastiejs
  • 27. USE OF CORE FEATURES • No pre and post methods. Use real events
  • 28. LACK OF ABILITY TO USE COMMON PROXIES • Easily be able to pull down and use a logger, security module, etc
  • 30. AND TO HAVE A LITTLE FUN…TO MAKE MY CODE PURR
  • 31. var purr = scarlet.plugins.purr; purr.when(Math,'min').play(); Math.min(1,2,3);
  • 32. SCARLETJS - THE PROJECT
  • 35. TESTING • Tools Used • Mocha • Builders ScarletBuilder.forInstance(<AnyInstance>) ScarletBuilder.forProperty(<AnyProperty>) .withInterceptors(<ArrayOfInterceptors>); ScarletBuilder.forMethod(<AnyMethod>) .withParameters(<AnyParams>) .withEvents(<AnyEvents>) .Assert();
  • 37. 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
  • 39. Scarlet.intercept(<ANYTHING>) .on(‘before’,<BEFORE_FUNC>) .on(‘after’,<AFTER_FUNC>) .on(‘done’,<DONE_FUNC>) .on(‘error’,<ERROR_FUNC>);
  • 43. var someProxy = Scarlet.intercept(<ANYFUNCTION>) .using(<INTERCEPTOR_FUNCTION>) .proxy();
  • 44. 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();
  • 46. PLUGINS • Scarlet Passport • Scarlet-winston • Scarlet-ioc • Scarlet-init
  • 47. var requestListener = scarletPassport .scarletPassport .authenticate('local', {}, requestListener)
  • 48. 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)
  • 49. function MyObjectB(myObjectA){ }; scarlet.plugins.ioc .register("myObjectA", MyObjectA) .register("myObjectB", MyObjectB); var myObjectB = scarlet .plugins .ioc .resolve("myObjectB"); myObjectB.anyMethod();
  • 51. ES6 - PROXIES ”A proxy object is an exotic object whose essential internal methods are partially implemented using ECMAScript code” – ES6 Draft October 2014
  • 52. 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; } });
  • 53. var awesemeoThing= {}; var proxiedThing = new Proxy(awesemeoThing,{ get: function(target, name){ console.log("In Get Proxy"); return target[name]; } }); var x = proxiedThing.any;
  • 54. var awesemeoThing= {}; var proxiedThing = new Proxy(awesemeoThing,{ set: function(target, name, value){ console.log("In Set Proxy"); target[name] = value; } }); proxiedThing.any = 'thing';
  • 55. NODE.JS PROXIES • Proxies can be enabled using the following commands: • $ node –harmony-proxies • $ node --harmony
  • 57. 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
  • 58. FIREFOX • Available in versions 18+
  • 59. PROXIES IN USE – NEGATIVE ARRAY
  • 60. var negativeArray = require('negative-array'); var unicorn = negativeArray(['pony', 'cake', 'rainbow']); console.log(unicorn[-1]);
  • 61. module.exports = function (arr) { … return new Proxy(arr, { get: function (target, name) { var i = +name; return target[i < 0 ? target.length + i : i]; }, }
  • 62. 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
  • 64. … var AnyAnnotation = function() {}; function simpleFunction() { return 'any'; } Object.defineProperty(simpleFunction, "annotations", { get: function() { return [new AnyAnnotation]; } });
  • 66. LOGGER ANNOTATIONS @Logger function simpleFunction () { return 'any'; }
  • 67. 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; }; };
  • 68. var createProxy = function(anyFunction){ return new Proxy(anyFunction, { apply : anyFunction. annotations[0] }); }; simpleFunction = createProxy(simpleFunction); simpleFunction();
  • 69. called simpleFunction Thu Oct 23 2014 23:33:02 GMT+0100 (GMT Daylight Time) with params: executed in:0
  • 70. THE FUTURE FOR SCARLETJS
  • 71. THANK YOU • @timchaplin • https://github.com/tjchaplin
  • 72. REFERENCES • http://soft.vub.ac.be/~tvcutsem/invokedynamic/proxies_tut orial • https://brendaneich.com/2012/10/harmony-of-dreams-come- true/ • http://wiki.ecmascript.org/doku.php?id=harmony:specifica tion_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