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 exports.isProxy = function(obj){ 102 var undef; 103 return obj !== undef && obj !== null && Proxy.isProxy(obj); 104 } 105 106 /** 107 * Creates a function proxy for an object. 108 * @param obj 109 * @param handler 110 * @param opts 111 */ 112 exports.createFunctionWrapper = function(obj, handler, opts) { 113 var ret = Proxy.createFunction(handlerMaker(obj), handler); 114 if(opts){ 115 Proxy.setPrototype(ret, opts); 116 } 117 return ret; 118 }; 119 120 121 exports.Proxy = Proxy;