1 var Proxy = require("node-proxy"), merge = require("./object").merge; 2 3 var handlerMaker = function(obj) { 4 return { 5 getOwnPropertyDescriptor: function(name) { 6 var desc = Object.getOwnPropertyDescriptor(obj, name); 7 // a trapping proxy's properties must always be configurable 8 if (desc !== undefined) { 9 desc.configurable = true; 10 } 11 return desc; 12 }, 13 getPropertyDescriptor: function(name) { 14 var desc = Object.getPropertyDescriptor(obj, name); // not in ES5 15 // a trapping proxy's properties must always be configurable 16 if (desc !== undefined) { 17 desc.configurable = true; 18 } 19 return desc; 20 }, 21 getOwnPropertyNames: function() { 22 return Object.getOwnPropertyNames(obj); 23 }, 24 getPropertyNames: function() { 25 return Object.getPropertyNames(obj); // not in ES5 26 }, 27 defineProperty: function(name, desc) { 28 Object.defineProperty(obj, name, desc); 29 }, 30 delete: function(name) { 31 return delete obj[name]; 32 }, 33 fix: function() { 34 if (Object.isFrozen(obj)) { 35 var result = {}; 36 Object.getOwnPropertyNames(obj).forEach(function(name) { 37 result[name] = Object.getOwnPropertyDescriptor(obj, name); 38 }); 39 return result; 40 } 41 // As long as obj is not frozen, the proxy won't allow itself to be fixed 42 return undefined; // will cause a TypeError to be thrown 43 }, 44 45 has: function(name) { 46 return name in obj; 47 }, 48 hasOwn: function(name) { 49 return ({}).hasOwnProperty.call(obj, name); 50 }, 51 get: function(receiver, name) { 52 return obj[name]; 53 }, 54 set: function(receiver, name, val) { 55 obj[name] = val; 56 return true; 57 }, // bad behavior when set fails in non-strict mode 58 enumerate: function() { 59 var result = []; 60 for (var name in obj) { 61 result.push(name); 62 } 63 return result; 64 }, 65 keys: function() { 66 return Object.keys(obj); 67 } 68 69 }; 70 }; 71 72 var noSuchMethodHandler = function(obj, handler) { 73 return { 74 get: function(receiver, name) { 75 return obj[name] ? obj[name] : handler.call(obj, name); 76 } 77 } 78 }; 79 80 /** 81 * Creates a proxy for an object. 82 * @param obj 83 * @param opts 84 */ 85 exports.handlerProxy = function(obj, opts) { 86 opts = opts || {}; 87 return Proxy.create(merge(handlerMaker(obj), opts)); 88 }; 89 90 /** 91 * creates a method missing proxy for an object 92 * @param obj 93 * @param handler 94 * @param opts 95 */ 96 exports.methodMissing = function(obj, handler, opts) { 97 opts = opts || {}; 98 return Proxy.create(merge(handlerMaker(obj), noSuchMethodHandler(obj, handler)), opts); 99 }; 100 101 /** 102 * Creates a function proxy for an object. 103 * @param obj 104 * @param handler 105 * @param opts 106 */ 107 exports.createFunctionWrapper = function(obj, handler, opts) { 108 var ret = Proxy.createFunction(handlerMaker(obj), handler); 109 if(opts){ 110 Proxy.setPrototype(ret, opts); 111 } 112 return ret; 113 }; 114 115 116 exports.Proxy = Proxy;