var EventEmitter = require('eventemitter3');

/**
  # rtc-proxy

  This is a set of simple proxy classes that are designed to provide a
  minimal layer between a WebRTC plugin and browser run JS.

  ## Why?

  This package exists because during the development of an iOS plugin, we
  have found that frameworks such as angular don't work as nicely with
  the plugin interface.  Primarily the problem is that Angular is unable
  to get any metainformation about the object (using `Object.keys` or
  similar).

  This layer provides that information when required.

**/
module.exports = function(prot, methods, attributes, events) {

  function capEvents(target, name) {
    var events = emitter(target);

    if (typeof target.__orig['on' + name] != 'function') {
      target.__orig['on' + name] = function() {
        events.emit.apply(events, [name].concat([].slice.call(arguments)));
      };
    }

    return events;
  }

  function emitter(target) {
    if (! target.__emitter) {
      target.__emitter = new EventEmitter();
    }

    return target.__emitter;
  }

  // patch methods
  (methods || []).forEach(function(method) {
    prot[method] = function() {
      var fn = this.__orig && this.__orig[method];

      if (typeof fn == 'function') {
        return fn.apply(this.__orig, arguments);
      }

      console.warn('could not invoke: ' + method);
    };
  });

  // patch properties
  (attributes || []).forEach(function(attrData) {
    var key = attrData[0];
    var readonly = attrData[1];
    var gs = {
      get: function() {
        return this.__orig[key];
      }
    };

    if (! readonly) {
      gs.set = function(value) {
        this.__orig[key] = value;
      };
    }

    Object.defineProperty(prot, key, gs);
  });

  (events || []).forEach(function(name) {
    Object.defineProperty(prot, 'on' + name, {
      get: function() {
        return emitter(this).listeners(name)[0];
      },

      set: function(handler) {
        var events = capEvents(this, name);

        if (! handler) {
          return events.removeAllListeners(name);
        }

        events.on(name, handler);
      }
    });
  });

  prot.addEventListener = function(name, handler) {
    capEvents(this, name).on(name, handler);
  };

  prot.removeEventListener = function(name, handler) {
    emitter(this).removeListener(name, handler);
  };

  return prot;
};

@@ -37,16 +37,52 @@
 tter3');
+%0Avar extend = require('cog/extend');
 %0A%0A/**%0A  
@@ -1520,45 +1520,23 @@
 var 
-readonly = attrData%5B1%5D;%0A    var gs = 
+flags = extend(
 %7B%0A  
@@ -1571,16 +1571,31 @@
   return
+ this.__orig &&
  this.__
@@ -1622,29 +1622,64 @@
    %7D
-;%0A%0A    if (! readonly
+, attrData%5B1%5D);%0A%0A    if (flags.writable && (! flags.set)
 ) %7B%0A
@@ -1684,16 +1684,19 @@
 %7B%0A      
+fla
 gs.set =
@@ -1710,24 +1710,53 @@
 on(value) %7B%0A
+        if (this.__orig) %7B%0A  
         this
@@ -1775,34 +1775,43 @@
  = value;%0A      
+  %7D%0A      
 %7D
-;
 %0A    %7D%0A%0A    Obje
@@ -1839,16 +1839,19 @@
 t, key, 
+fla
 gs);%0A  %7D
@@ -2245,16 +2245,34 @@
 %0A  %7D);%0A%0A
+  if (events) %7B%0A  
   prot.a
@@ -2311,24 +2311,26 @@
  handler) %7B%0A
+  
     capEvent
@@ -2362,22 +2362,26 @@
 ndler);%0A
+  
   %7D;%0A%0A
+  
   prot.r
@@ -2431,16 +2431,18 @@
 ) %7B%0A    
+  
 emitter(
@@ -2480,18 +2480,24 @@
 ler);%0A  
+  %7D;%0A  
 %7D
-;
 %0A%0A  retu

Change property definition implementation