Created
April 1, 2012 21:57
-
-
Save DavidBruant/2279059 to your computer and use it in GitHub Desktop.
Protected protocol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var d = new Person('David'); | |
console.log('d.name:', d.name); | |
setTimeout(function(){ | |
console.log('d age', d.getAge()); | |
}, 500); | |
console.log('d instanceof Person', d instanceof Person); | |
console.log('d instanceof ComputerSavvyPerson', d instanceof ComputerSavvyPerson); | |
var db = new ComputerSavvyPerson('David Bruant', 'JavaScript'); | |
console.log('db.name:', db.name); | |
console.log('db.favoriteLanguage:', db.favoriteLanguage); | |
console.log('first letter secret', db.getSecretFirstLetter()); | |
setTimeout(function(){ | |
console.log('db age', db.getAge()); | |
}, 500); | |
console.log('db instanceof Person', db instanceof Person); | |
console.log('db instanceof ComputerSavvyPerson', db instanceof ComputerSavvyPerson); | |
var eve = new EvilPerson(); | |
eve.attemptStealSecret(d); | |
eve.attemptStealSecret(db); | |
var eve2 = new EvilCompSavvyPerson(); | |
eve2.attemptStealSecret(d); | |
eve2.attemptStealSecret(db); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// COMPUTER SAVVY PERSON | |
var ComputerSavvyPerson = makeSubclass(Person, function(Protected, Super){ | |
function ComputerSavvyPerson(name, favoriteLanguage){ | |
console.log('this in ComputerSavvyPerson', this); | |
Super.call(this, name); | |
this.favoriteLanguage = favoriteLanguage; | |
} | |
ComputerSavvyPerson.prototype = Super.protoChain({ | |
getSecretFirstLetter : function(){ | |
return Protected(this).secret[0]; | |
} | |
}); | |
//console.log('ComputerSavvyPerson.prototype', ComputerSavvyPerson.prototype) | |
return ComputerSavvyPerson; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function evilPersonDecl(Protected, Super){ | |
function EvilPerson(){ | |
this.attemptStealSecret = function(otherPerson){ | |
//console.log('Evil Person', 'Protected(otherPerson).secret read') | |
var s = Protected(otherPerson).secret; | |
console.log("Ahah! I tried to steal %s's secret! Here is what I got:%s", otherPerson.name, String(s)); | |
} | |
} | |
return EvilPerson; | |
} | |
var EvilPerson = makeSubclass(Person, evilPersonDecl); | |
var EvilCompSavvyPerson = makeSubclass(ComputerSavvyPerson, evilPersonDecl); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// PERSON | |
var Person = makeConstructorWithProtected(function(Protected){ | |
function Person(name){ | |
Protected(this).secret = String(Math.random()).substr(2); | |
console.info("person's secret", Protected(this).secret, "...shhhhhhh!!!..."); | |
Protected(this).age = 0; | |
setInterval(function(){ | |
Protected(this).age++; | |
}.bind(this), 100); | |
this.name = name; | |
console.log('this in Person', this); | |
} | |
Person.prototype = { | |
getAge: function(){ | |
return Protected(this).age; | |
} | |
}; | |
return Person; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function makeProtectedStore(){ | |
var ownStore = new WeakMap(); | |
var childStoreGets = []; | |
var ret = function(o){ | |
var protectedStore; | |
// own store first | |
protectedStore = ownStore.get(o); | |
if(protectedStore) | |
return protectedStore; | |
// check in otherStores | |
childStoreGets.some(function(storeGet, i){ | |
//console.log('traversing childStores', childStores.length, i); | |
var s = storeGet(o); | |
if(s === Object(s)){ | |
protectedStore = s; | |
return true; | |
} | |
return false; | |
}); | |
if(protectedStore){ | |
return protectedStore; | |
} | |
else{ | |
var s = {}; // create new store | |
ownStore.set(o, s); | |
return s; | |
} | |
}; | |
ret.addChildStoreGet = childStoreGets.push.bind(childStoreGets); | |
ret.storeGet = ownStore.get.bind(ownStore); | |
return Object.freeze(ret); | |
} | |
(function(global){ | |
var constructorToProtectedStore = new WeakMap(); | |
global.makeConstructorWithProtected = function(declaration){ | |
var protectedStore = makeProtectedStore(); | |
var constructorWithProtected = declaration(protectedStore); | |
constructorToProtectedStore.set(constructorWithProtected, protectedStore); | |
return constructorWithProtected; | |
} | |
global.makeSubclass = function(parent, declaration){ | |
var protectedStore = makeProtectedStore(); | |
var parentProtectedStore = constructorToProtectedStore.get(parent); | |
parentProtectedStore.addChildStoreGet(protectedStore.storeGet); | |
var constructorWithProtected = declaration(protectedStore, Object.freeze({ | |
call: function(obj){ | |
var args = Array.prototype.slice.call(arguments, 1); | |
protectedStore(obj); // so that there is already an own protected store for the subclass instance | |
return parent.apply(obj, args); | |
}, | |
protoChain : function(obj){ | |
var proto = Object.create(parent.prototype); | |
Object.getOwnPropertyNames(obj).forEach(function(n){ | |
Object.defineProperty(proto, n, Object.getOwnPropertyDescriptor(obj, n)); | |
}); | |
return proto; | |
}, | |
prototype: parent.prototype | |
})); | |
constructorToProtectedStore.set(constructorWithProtected, protectedStore); | |
return constructorWithProtected; | |
} | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment