      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;