SlideShare a Scribd company logo
1 of 88
Download to read offline
Proxies
                              are Awesome!
                                    Brendan Eich
                          (w/ Mark Miller & Tom Van Cutsem)




Tuesday, September 28, 2010
ECMAScript 5 (ES5)



Tuesday, September 28, 2010
ES5 Review
           • Array extras
           • JSON (based on json2.js)
           • Strict Mode (“use strict”)
           • Object meta-programming API
            • accessor properties (getters & setters)
            • mutability and enumerability controls
            • “javascript.lang.reflect”
           • In Firefox 4, IE9 (w/o strict?), WebKit nightlies
Tuesday, September 28, 2010
ES5 Property Descriptors
  • Data vs. accessor properties
  • Property attributes
      var point =
        { x: 5,
          y: 8,
          get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } };
      Object.getOwnPropertyDescriptor(point, ‘x’);
          { value: 5,
            writable: true,
            enumerable: true,
            configurable: true }

      Object.getOwnPropertyDescriptor(point, ‘r’);
          { get: function () { return Math.sqrt(this.x*this.x + ...); },
            set: undefined,
            enumerable: true,
            configurable: true }
Tuesday, September 28, 2010
Property Descriptor Maps
  var point =
    { x: 5,
      y: 8,
      get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } };


  Object.defineProperty(point, ‘z’, {
    value: 0,
    enumerable: true,
    writable: false,
    configurable: false });



  var point = Object.create(
    Object.prototype,
    { x: { value: 5, ... }, y: { value: 8, ... },
      r: { get: function() {...}, enumerable: true, ... },
      z: { value: 0, enumerable: true, ... } });




Tuesday, September 28, 2010
Property Descriptor Maps
  var point =
    { x: 5,
      y: 8,
      get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } };


  Object.defineProperty(point, ‘z’, {
    value: 0,
    enumerable: true,
    writable: false,                                  name   pd
    configurable: false });                             x    {...}
                                                        y    {...}
                                                        r    {...}
  var point = Object.create(                             z   {...}
    Object.prototype,
    { x: { value: 5, ... }, y: { value: 8, ... },
      r: { get: function() {...}, enumerable: true, ... },
      z: { value: 0, enumerable: true, ... } });




Tuesday, September 28, 2010
Tamper-proofing Objects
          var point =
            { x: 5,
              y: 8,
              get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } };




          Object.preventExtensions(point);
          point.z = 0; // can’t add new properties



          Object.seal(point);
          delete point.x; // can’t delete properties


          Object.freeze(point);
          point.x = 7; // can’t assign properties




Tuesday, September 28, 2010
ES-Harmony Proxies



Tuesday, September 28, 2010
Dynamic Proxies

         •    Generic handling of property access:

             •     Generic wrappers: security, aspects, logging, profiling, ...

             •     Stratified form of SpiderMonkey’s __noSuchMethod__
                   js> o = {__noSuchMethod__: function (id, args) { print(id, args); }}

                   ({__noSuchMethod__:(function (id, args) {print(id, args);})})

                   js> o.m(1,2,3)

                   m 1,2,3


         •    Generic handling of other operations applicable to objects:

             •     Virtual objects: persistent objects, remote objects, ...

             •     Emulate the dreaded “host objects”

Tuesday, September 28, 2010
Example w/ just ES5: logging
   function makePoint(x, y) {
     return {
        x: x,
        y: y,
        ...
     };
   }




Tuesday, September 28, 2010
Example w/ just ES5: logging
   function makePoint(x, y) {
     return {
        x: x,
        y: y,
        ...
     };
   }
  function makeLoggedPoint(p) {
    return {
       get x() {
          log(‘get’,‘x’,p); return p.x;
       },
       set x(v) {
          log(‘set’,‘x’,p,v); p.x = v;
       },
       // get y, set y, ...
    };
  }
  var lp = makeLoggedPoint(makePoint(1,2));
Tuesday, September 28, 2010
Example w/ just ES5: logging
   function makePoint(x, y) {
     return {
        x: x,
        y: y,
        ...
     };
   }
  function makeLoggedPoint(p) {
    return {                              Too ad hoc. What about:
       get x() {                           • logging other data types
       },
          log(‘get’,‘x’,p); return p.x;
                                           • profiling, persistence,
       set x(v) {                          access control, ...
          log(‘set’,‘x’,p,v); p.x = v;
       },
       // get y, set y, ...
    };
  }
  var lp = makeLoggedPoint(makePoint(1,2));
Tuesday, September 28, 2010
Logging: static ES5 “proxies”
function makeLogger(obj) {
  var proxy = Object.create(Object.getProtoypeOf(obj), {});
  Object.getOwnPropertyNames(obj).forEach(function(name) {
    var pd = Object.getOwnPropertyDescriptor(obj, name);
    Object.defineProperty(proxy, name, {
      get: function() {
         log(‘get’, name, obj);
         return obj[name];
      },
      set: function(v) {
         log(‘set’, name, obj, v);
         obj[name] = v;
      },
      // copy attributes from pd
    });
  });
  return proxy;
}


Tuesday, September 28, 2010
Logging: static ES5 “proxies”
function makeLogger(obj) {
  var proxy = Object.create(Object.getProtoypeOf(obj), {});
  Object.getOwnPropertyNames(obj).forEach(function(name) {
    var pd = Object.getOwnPropertyDescriptor(obj, name);
    Object.defineProperty(proxy, name, {
      get: function() {
         log(‘get’, name, obj);

      },
         return obj[name];
                                    • proxy doesn’t reflect
      set: function(v) {            structural changes made to ‘obj’
         log(‘set’, name, obj, v);
         obj[name] = v;
                                    • structural changes made to
      },
                                    proxy are not reflected in ‘obj’
      // copy attributes from pd    • structural changes:
    });
  });
                                      • add/delete properties
  return proxy;                       • change property attributes
}


Tuesday, September 28, 2010
Logging: dynamic (harmony) proxies
   function makeLogger(obj) {
     var proxy = Proxy.create({
       get: function(rcvr, name) {
          log(‘get’, name, obj);
          return obj[name];
       },
       set: function(rcvr, name, val) {
          log(‘set’, name, obj, val);
          obj[name] = val;
          return true;
       },
       ...
     }, Object.getPrototypeOf(obj));
     return proxy;
   }




Tuesday, September 28, 2010
Logging: dynamic (harmony) proxies
   function makeLogger(obj) {
     var proxy = Proxy.create({
       get: function(rcvr, name) {
          log(‘get’, name, obj);                         handler
          return obj[name];
       },
       set: function(rcvr, name, val) {                            meta
          log(‘set’, name, obj, val);
                                          base
          obj[name] = val;
          return true;
       },
       ...                                       proxy
     }, Object.getPrototypeOf(obj));
     return proxy;
   }




Tuesday, September 28, 2010
Stratified API
            var proxy = Proxy.create(handler, proto);



                                                                handler


                                                                          meta
          base




                                                        proxy




Tuesday, September 28, 2010
Stratified API
            var proxy = Proxy.create(handler, proto);


            handler.get(proxy, ‘foo’)
                                                                handler


                                                                          meta
          base
                    proxy.foo



                                                        proxy




Tuesday, September 28, 2010
Stratified API
            var proxy = Proxy.create(handler, proto);


            handler.get(proxy, ‘foo’)
                                                                handler
            handler.set(proxy, ‘foo’, 42)



                                                                          meta
          base
                    proxy.foo
                    proxy.foo = 42

                                                        proxy




Tuesday, September 28, 2010
Stratified API
            var proxy = Proxy.create(handler, proto);


            handler.get(proxy, ‘foo’)
                                                                handler
            handler.set(proxy, ‘foo’, 42)

            handler.get(proxy, ‘foo’).apply(proxy,[1,2,3])

                                                                          meta
          base
                    proxy.foo
                    proxy.foo = 42
                    proxy.foo(1,2,3)                    proxy




Tuesday, September 28, 2010
Stratified API
            var proxy = Proxy.create(handler, proto);


            handler.get(proxy, ‘foo’)
                                                                handler
            handler.set(proxy, ‘foo’, 42)

            handler.get(proxy, ‘foo’).apply(proxy,[1,2,3])

            handler.get(proxy, ‘get’)                                     meta
          base
                    proxy.foo
                    proxy.foo = 42
                    proxy.foo(1,2,3)                    proxy
                    proxy.get




Tuesday, September 28, 2010
Stratified API
            var proxy = Proxy.create(handler, proto);


            handler.get(proxy, ‘foo’)
                                                                handler
            handler.set(proxy, ‘foo’, 42)

            handler.get(proxy, ‘foo’).apply(proxy,[1,2,3])

            handler.get(proxy, ‘get’)                                     meta
          base
                    proxy.foo
                    proxy.foo = 42
                    proxy.foo(1,2,3)                    proxy         proto
                    proxy.get




Tuesday, September 28, 2010
Not just property accesses
            var proxy = Proxy.create(handler, proto);




                                                                handler



                                                                          meta
          base




                                                        proxy




Tuesday, September 28, 2010
Not just property accesses
            var proxy = Proxy.create(handler, proto);

              handler.has(‘foo’)



                                                                handler



                                                                          meta
          base

              ‘foo’ in proxy

                                                        proxy




Tuesday, September 28, 2010
Not just property accesses
            var proxy = Proxy.create(handler, proto);

              handler.has(‘foo’)

              handler.delete(‘foo’)

                                                                handler



                                                                          meta
          base

              ‘foo’ in proxy

              delete proxy.foo                          proxy




Tuesday, September 28, 2010
Not just property accesses
            var proxy = Proxy.create(handler, proto);

              handler.has(‘foo’)

              handler.delete(‘foo’)
              var props = handler.enumerate();
                                                                handler
              for (var i=0;i<props.length;i++) {
                var prop = props[i]; ...
              }
                                                                          meta
          base

              ‘foo’ in proxy

              delete proxy.foo                          proxy
              for (var prop in proxy) { ... }




Tuesday, September 28, 2010
Not just property accesses
            var proxy = Proxy.create(handler, proto);

              handler.has(‘foo’)

              handler.delete(‘foo’)
              var props = handler.enumerate();
                                                                handler
              for (var i=0;i<props.length;i++) {
                var prop = props[i]; ...
              }
              handler.defineProperty(‘foo’, pd)                           meta
          base

              ‘foo’ in proxy

              delete proxy.foo                          proxy
              for (var prop in proxy) { ... }

              Object.defineProperty(proxy,‘foo’, pd)


Tuesday, September 28, 2010
But not quite everything, either
            var proxy = Proxy.create(handler, proto);




                                                                handler



                                                                          meta
          base




                                                        proxy




Tuesday, September 28, 2010
But not quite everything, either
            var proxy = Proxy.create(handler, proto);




                                                                handler



                                                                          meta
          base

              proxy === obj

                                                        proxy




Tuesday, September 28, 2010
But not quite everything, either
            var proxy = Proxy.create(handler, proto);




                                                                handler



                                                                          meta
          base

              proxy === obj

              Object.getPrototypeOf(proxy) => proto     proxy         proto




Tuesday, September 28, 2010
But not quite everything, either
            var proxy = Proxy.create(handler, proto);




                                                                handler



                                                                          meta
          base

              proxy === obj

              Object.getPrototypeOf(proxy) => proto     proxy         proto
              proxy instanceof SomeFunction




Tuesday, September 28, 2010
But not quite everything, either
            var proxy = Proxy.create(handler, proto);




                                                                handler



                                                                          meta
          base

              proxy === obj

              Object.getPrototypeOf(proxy) => proto     proxy         proto
              proxy instanceof SomeFunction

              typeof proxy => “object”


Tuesday, September 28, 2010
Full Handler API
                                                            handler


                                proxy

Object.getOwnPropertyDescriptor(proxy)              handler.getOwnPropertyDescriptor(name)
     Object.getPropertyDescriptor(proxy)            handler.getPropertyDescriptor(name)
    Object.defineProperty(proxy,name,pd)            handler.defineProperty(name, pd)
        Object.getOwnPropertyNames(proxy)  handler.getOwnPropertyNames()
                                delete proxy.name   handler.delete(name) 
                  for (name in proxy) { ... }  handler.enumerate()
           Object.{freeze|seal|...}(proxy)          handler.fix()
                                    name in proxy   handler.has(name)
  ({}).hasOwnProperty.call(proxy, name)             handler.hasOwn(name)
                                    receiver.name   handler.get(receiver, name)
                              receiver.name = val   handler.set(receiver, name, val)
                               Object.keys(proxy)   handler.keys()
                  for (name in proxy) { ... }       handler.iterate()

Tuesday, September 28, 2010
Fundamental vs Derived Traps
                                                         handler


                              proxy

                                               Fundamental traps
     Object.getOwnPropertyDescriptor(proxy)    handler.getOwnPropertyDescriptor(name)
        Object.getPropertyDescriptor(proxy)    handler.getPropertyDescriptor(name)
       Object.defineProperty(proxy,name,pd)    handler.defineProperty(name, pd)
          Object.getOwnPropertyNames(proxy)    handler.getOwnPropertyNames()
                          delete proxy.name    handler.delete(name) 
                for (name in proxy) { ... }    handler.enumerate() -> [string]
            Object.{freeze|seal|...}(proxy)    handler.fix()




                                               Derived traps
                              name in proxy    handler.has(name)
      ({}).hasOwnProperty.call(proxy, name)    handler.hasOwn(name)
                              receiver.name    handler.get(receiver, name)
                        receiver.name = val    handler.set(receiver, name, val)
                         Object.keys(proxy)    handler.keys()
                for (name in proxy) { ... }    handler.iterate() -> iterator




Tuesday, September 28, 2010
Function Proxies
        JavaScript functions are objects. Additionally,
        they are also callable and constructible
     var call = function() { ... };
     var construct = function() { ... };
     var funproxy = Proxy.createFunction(handler, call, construct);

                                                 handler
                                                           call construct




                                                    funproxy



Tuesday, September 28, 2010
Function Proxies
        JavaScript functions are objects. Additionally,
        they are also callable and constructible
     var call = function() { ... };
     var construct = function() { ... };
     var funproxy = Proxy.createFunction(handler, call, construct);

                  call(1,2,3)                    handler
                                                           call construct



                  funproxy(1,2,3)


                                                    funproxy



Tuesday, September 28, 2010
Function Proxies
        JavaScript functions are objects. Additionally,
        they are also callable and constructible
     var call = function() { ... };
     var construct = function() { ... };
     var funproxy = Proxy.createFunction(handler, call, construct);

                  call(1,2,3)                    handler
                                                           call construct
                  construct(1,2,3)




                  funproxy(1,2,3)

                  new funproxy(1,2,3)
                                                    funproxy



Tuesday, September 28, 2010
Function Proxies
        JavaScript functions are objects. Additionally,
        they are also callable and constructible
     var call = function() { ... };
     var construct = function() { ... };
     var funproxy = Proxy.createFunction(handler, call, construct);

                  call(1,2,3)                         handler
                                                                call construct
                  construct(1,2,3)
                  handler.get(funproxy,‘prototype’)


                  funproxy(1,2,3)

                  new funproxy(1,2,3)

                  funproxy.prototype                     funproxy



Tuesday, September 28, 2010
Function Proxies
        JavaScript functions are objects. Additionally,
        they are also callable and constructible
     var call = function() { ... };
     var construct = function() { ... };
     var funproxy = Proxy.createFunction(handler, call, construct);

                  call(1,2,3)                         handler
                                                                call construct
                  construct(1,2,3)
                  handler.get(funproxy,‘prototype’)


                  funproxy(1,2,3)

                  new funproxy(1,2,3)

                  funproxy.prototype                     funproxy
                  typeof funproxy => “function”


Tuesday, September 28, 2010
Function Proxies
        JavaScript functions are objects. Additionally,
        they are also callable and constructible
     var call = function() { ... };
     var construct = function() { ... };
     var funproxy = Proxy.createFunction(handler, call, construct);

                  call(1,2,3)                          handler
                                                                 call construct
                  construct(1,2,3)
                  handler.get(funproxy,‘prototype’)


                  funproxy(1,2,3)

                  new funproxy(1,2,3)

                  funproxy.prototype                      funproxy
                  typeof funproxy => “function”
                  Object.getPrototypeOf(funproxy) => Function.prototype
Tuesday, September 28, 2010
Dilemma: Invoke vs Get+Call
               • Fundamental vs derived traps = tradeoff in
                     performance (method allocation or caching)
                     vs. consistency
                              var p = Proxy.create({
                                get:    function(receiver, name) { ... },
                                invoke: function(receiver, name, args) { ... },
                                ...
                              });

                              p.x;      // get(p,'x')
                              p.m(a);   // invoke(p, 'm', [a])


               • invoke can intercept arguments
               • but notably, JS methods can be extracted as
                     functions and called later (functional FTW!)
               • breaks invariant o.m.call(o) <=> o.m()
Tuesday, September 28, 2010
Selective Interception




                                                       meta
                 base




                                   object




Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)



                                                             meta
                 base




                                   object

                                            JavaScript territory


Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)
                                      VM handler


                                                                    meta
                 base




                                   object

                                                   JavaScript territory


Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)
                              VM handler   VM handler


                                                                         meta
                 base




                 host object           object

                                                        JavaScript territory


Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)
                              VM handler   VM handler              handler


                                                                             meta
                 base




                 host object           object              proxy

                                                        JavaScript territory


Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)
                              VM handler   VM handler              handler


                                                                             meta
                 base




                 host object           object              proxy

                                                        JavaScript territory


Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)                      Self-hosted
                              VM handler   VM handler              handler


                                                                             meta
                 base




                 host object           object              proxy

                                                        JavaScript territory


Tuesday, September 28, 2010
Selective Interception

                   VM territory (C++)                      Self-hosted
                              VM handler   VM handler              handler


                                                                             meta
                 base




                 host object           object              proxy

                                                        JavaScript territory


Tuesday, September 28, 2010
Example: no-op forwarding proxy
                                                     handler

    function ForwardingHandler(obj) {
      this.target = obj;                           proxy    target
    }
    ForwardingHandler.prototype = {
      has: function(name) { return name in this.target; },
      get: function(rcvr,name) { return this.target[name]; },
      set: function(rcvr,name,val) { this.target[name]=val;return true; },
      delete: function(name) { return delete this.target[name]; }
      enumerate: function() {
        var props = [];
         for (name in this.target) { props.push(name); };
         return props;
      },
      ...
    }

    var proxy = Proxy.create(new ForwardingHandler(o),
                             Object.getPrototypeOf(o));
Tuesday, September 28, 2010
Example: counting property access
            function makeSimpleProfiler(target) {
              var forwarder = new ForwardingHandler(target);
              var count = Object.create(null);
              forwarder.get = function(rcvr, name) {
                 count[name] = (count[name] || 0) + 1;
                 return this.target[name];
              };
              return {
                 proxy: Proxy.create(forwarder,
                                     Object.getPrototypeOf(target)),
                 get stats() { return count; }
              }
            }




Tuesday, September 28, 2010
Example: counting property access
            function makeSimpleProfiler(target) {
              var forwarder = new ForwardingHandler(target);
              var count = Object.create(null);
              forwarder.get = function(rcvr, name) {
                 count[name] = (count[name] || 0) + 1;
                 return this.target[name];
              };
              return {
                 proxy: Proxy.create(forwarder,
                                     Object.getPrototypeOf(target)),
                 get stats() { return count; }
              }
            }

            var subject = { ... };
            var profiler = makeSimpleProfiler(subject);
            runApp(profiler.proxy);
            display(profiler.stats);

Tuesday, September 28, 2010
Fixing a Proxy
            var proxy = Proxy.create(handler, proto);



                                                                handler


                                                                          meta
          base




                                                        proxy




Tuesday, September 28, 2010
Fixing a Proxy
            var proxy = Proxy.create(handler, proto);



                                                                handler


                                                                          meta
          base

           Object.freeze(proxy)

           Object.seal(proxy)
                                                        proxy
           Object.preventExtensions(proxy)




Tuesday, September 28, 2010
Fixing a Proxy
            var proxy = Proxy.create(handler, proto);


           var pdmap = handler.fix();
           if (pdmap === undefined) throw TypeError();           handler
           become(proxy,
                  Object.freeze(
                     Object.create(proto, pdmap)));
                                                                           meta
          base

           Object.freeze(proxy)

           Object.seal(proxy)
                                                         proxy
           Object.preventExtensions(proxy)




Tuesday, September 28, 2010
Fixing a Proxy
            var proxy = Proxy.create(handler, proto);


           var pdmap = handler.fix();
           if (pdmap === undefined) throw TypeError();           handler
           become(proxy,
                  Object.freeze(
                     Object.create(proto, pdmap)));
                                                                           meta
          base

           Object.freeze(proxy)

           Object.seal(proxy)
                                                         proxy
           Object.preventExtensions(proxy)




                                         fix
                              Trapping          Fixed
Tuesday, September 28, 2010
Fixing a Proxy
            var proxy = Proxy.create(handler, proto);


           var pdmap = handler.fix();
           if (pdmap === undefined) throw TypeError();
           become(proxy,
                  Object.freeze(
                     Object.create(proto, pdmap)));
                                                                 meta
          base

           Object.freeze(proxy)

           Object.seal(proxy)
                                                         proxy
           Object.preventExtensions(proxy)




                                         fix
                              Trapping          Fixed
Tuesday, September 28, 2010
Meta-level Shifting
                                                        handler


                              proxy
    Object.getOwnPropertyDescriptor(proxy)    handler.getOwnPropertyDescriptor(name)
       Object.getPropertyDescriptor(proxy)    handler.getPropertyDescriptor(name)
      Object.defineProperty(proxy,name,pd)    handler.defineProperty(name, pd)
         Object.getOwnPropertyNames(proxy)    handler.getOwnPropertyNames()
                         delete proxy.name    handler.delete(name) 
               for (name in proxy) { ... }    handler.enumerate()
           Object.{freeze|seal|...}(proxy)    handler.fix()
                             name in proxy    handler.has(name)
     ({}).hasOwnProperty.call(proxy, name)    handler.hasOwn(name)
                             receiver.name    handler.get(receiver, name)
                       receiver.name = val    handler.set(receiver, name, val)
                        Object.keys(proxy)    handler.keys()
               for (name in proxy) { ... }    handler.iterate()


        base-level: many operations           meta-level: all operations reified as
                on objects                           invocations of traps


Tuesday, September 28, 2010
Meta-level Shifting
 a proxy whose                                           μhandler

handler is a proxy
                              handler


     handler.getOwnPropertyDescriptor(name)   μhandler.get(handler,   ‘getOwnP..’)(name)
     handler.getPropertyDescriptor(name)      μhandler.get(handler,   ‘getProp..’)(name)
     handler.defineOwnProperty(name, pd)      μhandler.get(handler,   ‘define...’)(name,pd)
     handler.delete(name)                     μhandler.get(handler,   ‘delete’)(name)
     handler.getOwnPropertyNames()            μhandler.get(handler,   ‘getOwnP..’)()
     handler.enumerate()                      μhandler.get(handler,   ‘enumerate’)()
     handler.fix()                            μhandler.get(handler,   ‘fix’)()
     handler.has(name)                        μhandler.get(handler,   ‘has’)(name)
     handler.hasOwn(name)                     μhandler.get(handler,   ‘hasOwn’)(name)
     handler.get(receiver, name)              μhandler.get(handler,   ‘get’)(receiver,name)
     handler.set(receiver, name, val)         μhandler.get(handler,   ‘set’)(receiver,name,val)
     handler.keys()                           μhandler.get(handler,   ‘keys’)()
     handler.iterate()                        μhandler.get(handler,   ‘iterate’)()

   meta-level: all operations reified as           meta-meta-level: all operations
          invocations of traps                   reified as invocations of ‘get’ trap


Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          • Firefox security wrappers (anti-XSS, XUL, etc.)
          • Google Caja: capability-secure subset
          • Object-capability model: an object is powerless
                unless given a reference to other objects
          • References can be made revocable through a
                membrane




Tuesday, September 28, 2010
Example: Membranes
          function makeSimpleMembrane(initTarget) {
            var enabled = true;




          }

Tuesday, September 28, 2010
Example: Membranes
          function makeSimpleMembrane(initTarget) {
            var enabled = true;




            return {
               wrapper: wrap(initTarget),
               revoke: function() { enabled = false; }
            };
          }

Tuesday, September 28, 2010
Example: Membranes
          function makeSimpleMembrane(initTarget) {
            var enabled = true;




            function wrap(target) {
              if (Object.isPrimitive(target)) { return target; }
              var baseHandler = new ForwardingHandler(target);
              var revokeHandler = Proxy.create({
                get: function(rcvr, name) { return wrapFunction(baseHandler[name]); }
              });




            }
            return {
               wrapper: wrap(initTarget),
               revoke: function() { enabled = false; }
            };
          }

Tuesday, September 28, 2010
Example: Membranes
          function makeSimpleMembrane(initTarget) {
            var enabled = true;




            function wrap(target) {
              if (Object.isPrimitive(target)) { return target; }
              var baseHandler = new ForwardingHandler(target);
              var revokeHandler = Proxy.create({
                get: function(rcvr, name) { return wrapFunction(baseHandler[name]); }
              });

              if (typeof target === “function”) {
                return Proxy.createFunction(revokeHandler, wrapFunction(target));
              }
              return Proxy.create(revokeHandler, wrap(Object.getPrototypeOf(target)));
            }
            return {
               wrapper: wrap(initTarget),
               revoke: function() { enabled = false; }
            };
          }

Tuesday, September 28, 2010
Example: Membranes
          function makeSimpleMembrane(initTarget) {
            var enabled = true;
            function wrapFunction(f) {
              return function() { // variable-argument function
                if (!enabled) { throw new Error("revoked"); }
               return wrap(f.apply(wrap(this), arguments.map(wrap)));
              }
            }
            function wrap(target) {
              if (Object.isPrimitive(target)) { return target; }
              var baseHandler = new ForwardingHandler(target);
              var revokeHandler = Proxy.create({
                get: function(rcvr, name) { return wrapFunction(baseHandler[name]); }
              });

              if (typeof target === “function”) {
                return Proxy.createFunction(revokeHandler, wrapFunction(target));
              }
              return Proxy.create(revokeHandler, wrap(Object.getPrototypeOf(target)));
            }
            return {
               wrapper: wrap(initTarget),
               revoke: function() { enabled = false; }
            };
          }

Tuesday, September 28, 2010
Prior Work



                        handler


                                               meta
   base



              proxy




Tuesday, September 28, 2010
Prior Work



                        handler            mirror     ProxyHandler   InvocationHandler


                                                                                   meta
   base



              proxy               mirage            proxy      java.lang.reflect.Proxy




Tuesday, September 28, 2010
Prior Work



                        handler             mirror     ProxyHandler   InvocationHandler


                                                                                     meta
   base



              proxy                mirage            proxy       java.lang.reflect.Proxy

 # traps                      13             30              3               1

Tuesday, September 28, 2010
Making JavaScript Extensible


          • Extending JavaScript today: “Host objects”
                (the IE DOM; anything implemented in C++)
          • Proxies are sufficiently powerful to emulate most
                of the behavior of host objects in JavaScript itself
          • Two possible avenues to close the gap:
           • Make proxies even more powerful
           • Make host objects only as powerful as proxies
Tuesday, September 28, 2010
Status

         • Presented at ECMA TC-39 meetings
         • Approved for inclusion in ES-Harmony
         • http://wiki.ecmascript.org/doku.php?
              id=harmony:proxies
         • In Firefox 4 already, thanks to Andreas Gal!
          • The basis of all of Gecko’s security wrappers
          • Used by Zaphod (Narcissus as JS engine add-on,
                   source at http://github.com/taustin/Zaphod/)


Tuesday, September 28, 2010
Lessons for Web Standards
           • Standards need savvy academic research
           • Standards must evolve quickly on the Web
           • They can’t evolve without prototype trials
           • These experiments need tons of user-testing
           • To reach users at scale, prototypes must ship
           • Ecma TC39 committed to prototyping specs
                 before finalizing standards
           • Committee members work together, no
                 blind-siding, to uphold Harmony (it’s social!)

Tuesday, September 28, 2010
Micro-benchmark Results




Tuesday, September 28, 2010
Micro-benchmark: Overhead




Tuesday, September 28, 2010
Proxies: Summary

         •    Proxies enable:

             •     Generic wrappers: access control, profiling,
                   adaptors, test injection, etc.

             •     Virtual objects: persistent objects, remote objects,
                   emulated host objects, ...

         •    API:

             •     Robust: stratified, not all operations intercepted

             •     Secure: can’t trap non-proxy or fixed objects

             •     Performance: no overhead for non-proxy objects


Tuesday, September 28, 2010
Conclusions

               • ES5 provides new meta-programming APIs
               • ES-Harmony Proxies: robust dynamic meta-
                     programming for virtual objects, wrappers
               • Proxies help put developers in control of
                     extending JavaScript, instead of Ecma TC39
               • JavaScript: the Revenge of Smalltalk!


Tuesday, September 28, 2010

More Related Content

What's hot

What's hot (20)

Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
JUnit 4
JUnit 4JUnit 4
JUnit 4
 
Fetch API Talk
Fetch API TalkFetch API Talk
Fetch API Talk
 
Javascript validating form
Javascript validating formJavascript validating form
Javascript validating form
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Top 10 RxJs Operators in Angular
Top 10 RxJs Operators in Angular Top 10 RxJs Operators in Angular
Top 10 RxJs Operators in Angular
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
 
JavaScript Fetch API
JavaScript Fetch APIJavaScript Fetch API
JavaScript Fetch API
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in Golang
 
API for Beginners
API for BeginnersAPI for Beginners
API for Beginners
 
Expressjs
ExpressjsExpressjs
Expressjs
 
Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
ES6 presentation
ES6 presentationES6 presentation
ES6 presentation
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017
 
PHP and Mysql
PHP and MysqlPHP and Mysql
PHP and Mysql
 
Introduction to Node js
Introduction to Node jsIntroduction to Node js
Introduction to Node js
 
Data Types In PHP
Data Types In PHPData Types In PHP
Data Types In PHP
 

Similar to Proxies are Awesome!

HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
Kris Kowal
 
Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
Adam Lu
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
Miao Siyu
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
偉格 高
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
Juriy Zaytsev
 

Similar to Proxies are Awesome! (20)

HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
ECMAScript 5: Новое в JavaScript
ECMAScript 5: Новое в JavaScriptECMAScript 5: Новое в JavaScript
ECMAScript 5: Новое в JavaScript
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
 
Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
 
JSConf: All You Can Leet
JSConf: All You Can LeetJSConf: All You Can Leet
JSConf: All You Can Leet
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
 
ekb.py - Python VS ...
ekb.py - Python VS ...ekb.py - Python VS ...
ekb.py - Python VS ...
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design Patterns
 
Understanding JavaScript
Understanding JavaScriptUnderstanding JavaScript
Understanding JavaScript
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Javascript Basics
Javascript BasicsJavascript Basics
Javascript Basics
 
A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVM
 

More from Brendan Eich

More from Brendan Eich (20)

Int64
Int64Int64
Int64
 
Always bet on JS - Finjs.io NYC 2016
Always bet on JS - Finjs.io NYC 2016Always bet on JS - Finjs.io NYC 2016
Always bet on JS - Finjs.io NYC 2016
 
dotJS 2015
dotJS 2015dotJS 2015
dotJS 2015
 
Extensible Operators and Literals for JavaScript
Extensible Operators and Literals for JavaScriptExtensible Operators and Literals for JavaScript
Extensible Operators and Literals for JavaScript
 
Fluent15
Fluent15Fluent15
Fluent15
 
The Same-Origin Saga
The Same-Origin SagaThe Same-Origin Saga
The Same-Origin Saga
 
Taysom seminar
Taysom seminarTaysom seminar
Taysom seminar
 
Fluent14
Fluent14Fluent14
Fluent14
 
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
 
My dotJS Talk
My dotJS TalkMy dotJS Talk
My dotJS Talk
 
Web futures
Web futuresWeb futures
Web futures
 
JS Responsibilities
JS ResponsibilitiesJS Responsibilities
JS Responsibilities
 
Value objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progressValue objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progress
 
Mozilla Research Party Talk
Mozilla Research Party TalkMozilla Research Party Talk
Mozilla Research Party Talk
 
Splash
SplashSplash
Splash
 
JSLOL
JSLOLJSLOL
JSLOL
 
Capitol js
Capitol jsCapitol js
Capitol js
 
Paren free
Paren freeParen free
Paren free
 
Txjs talk
Txjs talkTxjs talk
Txjs talk
 
Mozilla's NodeConf talk
Mozilla's NodeConf talkMozilla's NodeConf talk
Mozilla's NodeConf talk
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

Proxies are Awesome!

  • 1. Proxies are Awesome! Brendan Eich (w/ Mark Miller & Tom Van Cutsem) Tuesday, September 28, 2010
  • 2. ECMAScript 5 (ES5) Tuesday, September 28, 2010
  • 3. ES5 Review • Array extras • JSON (based on json2.js) • Strict Mode (“use strict”) • Object meta-programming API • accessor properties (getters & setters) • mutability and enumerability controls • “javascript.lang.reflect” • In Firefox 4, IE9 (w/o strict?), WebKit nightlies Tuesday, September 28, 2010
  • 4. ES5 Property Descriptors • Data vs. accessor properties • Property attributes var point = { x: 5, y: 8, get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } }; Object.getOwnPropertyDescriptor(point, ‘x’); { value: 5, writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptor(point, ‘r’); { get: function () { return Math.sqrt(this.x*this.x + ...); }, set: undefined, enumerable: true, configurable: true } Tuesday, September 28, 2010
  • 5. Property Descriptor Maps var point = { x: 5, y: 8, get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } }; Object.defineProperty(point, ‘z’, { value: 0, enumerable: true, writable: false, configurable: false }); var point = Object.create( Object.prototype, { x: { value: 5, ... }, y: { value: 8, ... }, r: { get: function() {...}, enumerable: true, ... }, z: { value: 0, enumerable: true, ... } }); Tuesday, September 28, 2010
  • 6. Property Descriptor Maps var point = { x: 5, y: 8, get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } }; Object.defineProperty(point, ‘z’, { value: 0, enumerable: true, writable: false, name pd configurable: false }); x {...} y {...} r {...} var point = Object.create( z {...} Object.prototype, { x: { value: 5, ... }, y: { value: 8, ... }, r: { get: function() {...}, enumerable: true, ... }, z: { value: 0, enumerable: true, ... } }); Tuesday, September 28, 2010
  • 7. Tamper-proofing Objects var point = { x: 5, y: 8, get r() { return Math.sqrt(this.x*this.x + this.y*this.y); } }; Object.preventExtensions(point); point.z = 0; // can’t add new properties Object.seal(point); delete point.x; // can’t delete properties Object.freeze(point); point.x = 7; // can’t assign properties Tuesday, September 28, 2010
  • 9. Dynamic Proxies • Generic handling of property access: • Generic wrappers: security, aspects, logging, profiling, ... • Stratified form of SpiderMonkey’s __noSuchMethod__ js> o = {__noSuchMethod__: function (id, args) { print(id, args); }} ({__noSuchMethod__:(function (id, args) {print(id, args);})}) js> o.m(1,2,3) m 1,2,3 • Generic handling of other operations applicable to objects: • Virtual objects: persistent objects, remote objects, ... • Emulate the dreaded “host objects” Tuesday, September 28, 2010
  • 10. Example w/ just ES5: logging function makePoint(x, y) { return { x: x, y: y, ... }; } Tuesday, September 28, 2010
  • 11. Example w/ just ES5: logging function makePoint(x, y) { return { x: x, y: y, ... }; } function makeLoggedPoint(p) { return { get x() { log(‘get’,‘x’,p); return p.x; }, set x(v) { log(‘set’,‘x’,p,v); p.x = v; }, // get y, set y, ... }; } var lp = makeLoggedPoint(makePoint(1,2)); Tuesday, September 28, 2010
  • 12. Example w/ just ES5: logging function makePoint(x, y) { return { x: x, y: y, ... }; } function makeLoggedPoint(p) { return { Too ad hoc. What about: get x() { • logging other data types }, log(‘get’,‘x’,p); return p.x; • profiling, persistence, set x(v) { access control, ... log(‘set’,‘x’,p,v); p.x = v; }, // get y, set y, ... }; } var lp = makeLoggedPoint(makePoint(1,2)); Tuesday, September 28, 2010
  • 13. Logging: static ES5 “proxies” function makeLogger(obj) { var proxy = Object.create(Object.getProtoypeOf(obj), {}); Object.getOwnPropertyNames(obj).forEach(function(name) { var pd = Object.getOwnPropertyDescriptor(obj, name); Object.defineProperty(proxy, name, { get: function() { log(‘get’, name, obj); return obj[name]; }, set: function(v) { log(‘set’, name, obj, v); obj[name] = v; }, // copy attributes from pd }); }); return proxy; } Tuesday, September 28, 2010
  • 14. Logging: static ES5 “proxies” function makeLogger(obj) { var proxy = Object.create(Object.getProtoypeOf(obj), {}); Object.getOwnPropertyNames(obj).forEach(function(name) { var pd = Object.getOwnPropertyDescriptor(obj, name); Object.defineProperty(proxy, name, { get: function() { log(‘get’, name, obj); }, return obj[name]; • proxy doesn’t reflect set: function(v) { structural changes made to ‘obj’ log(‘set’, name, obj, v); obj[name] = v; • structural changes made to }, proxy are not reflected in ‘obj’ // copy attributes from pd • structural changes: }); }); • add/delete properties return proxy; • change property attributes } Tuesday, September 28, 2010
  • 15. Logging: dynamic (harmony) proxies function makeLogger(obj) { var proxy = Proxy.create({ get: function(rcvr, name) { log(‘get’, name, obj); return obj[name]; }, set: function(rcvr, name, val) { log(‘set’, name, obj, val); obj[name] = val; return true; }, ... }, Object.getPrototypeOf(obj)); return proxy; } Tuesday, September 28, 2010
  • 16. Logging: dynamic (harmony) proxies function makeLogger(obj) { var proxy = Proxy.create({ get: function(rcvr, name) { log(‘get’, name, obj); handler return obj[name]; }, set: function(rcvr, name, val) { meta log(‘set’, name, obj, val); base obj[name] = val; return true; }, ... proxy }, Object.getPrototypeOf(obj)); return proxy; } Tuesday, September 28, 2010
  • 17. Stratified API var proxy = Proxy.create(handler, proto); handler meta base proxy Tuesday, September 28, 2010
  • 18. Stratified API var proxy = Proxy.create(handler, proto); handler.get(proxy, ‘foo’) handler meta base proxy.foo proxy Tuesday, September 28, 2010
  • 19. Stratified API var proxy = Proxy.create(handler, proto); handler.get(proxy, ‘foo’) handler handler.set(proxy, ‘foo’, 42) meta base proxy.foo proxy.foo = 42 proxy Tuesday, September 28, 2010
  • 20. Stratified API var proxy = Proxy.create(handler, proto); handler.get(proxy, ‘foo’) handler handler.set(proxy, ‘foo’, 42) handler.get(proxy, ‘foo’).apply(proxy,[1,2,3]) meta base proxy.foo proxy.foo = 42 proxy.foo(1,2,3) proxy Tuesday, September 28, 2010
  • 21. Stratified API var proxy = Proxy.create(handler, proto); handler.get(proxy, ‘foo’) handler handler.set(proxy, ‘foo’, 42) handler.get(proxy, ‘foo’).apply(proxy,[1,2,3]) handler.get(proxy, ‘get’) meta base proxy.foo proxy.foo = 42 proxy.foo(1,2,3) proxy proxy.get Tuesday, September 28, 2010
  • 22. Stratified API var proxy = Proxy.create(handler, proto); handler.get(proxy, ‘foo’) handler handler.set(proxy, ‘foo’, 42) handler.get(proxy, ‘foo’).apply(proxy,[1,2,3]) handler.get(proxy, ‘get’) meta base proxy.foo proxy.foo = 42 proxy.foo(1,2,3) proxy proto proxy.get Tuesday, September 28, 2010
  • 23. Not just property accesses var proxy = Proxy.create(handler, proto); handler meta base proxy Tuesday, September 28, 2010
  • 24. Not just property accesses var proxy = Proxy.create(handler, proto); handler.has(‘foo’) handler meta base ‘foo’ in proxy proxy Tuesday, September 28, 2010
  • 25. Not just property accesses var proxy = Proxy.create(handler, proto); handler.has(‘foo’) handler.delete(‘foo’) handler meta base ‘foo’ in proxy delete proxy.foo proxy Tuesday, September 28, 2010
  • 26. Not just property accesses var proxy = Proxy.create(handler, proto); handler.has(‘foo’) handler.delete(‘foo’) var props = handler.enumerate(); handler for (var i=0;i<props.length;i++) { var prop = props[i]; ... } meta base ‘foo’ in proxy delete proxy.foo proxy for (var prop in proxy) { ... } Tuesday, September 28, 2010
  • 27. Not just property accesses var proxy = Proxy.create(handler, proto); handler.has(‘foo’) handler.delete(‘foo’) var props = handler.enumerate(); handler for (var i=0;i<props.length;i++) { var prop = props[i]; ... } handler.defineProperty(‘foo’, pd) meta base ‘foo’ in proxy delete proxy.foo proxy for (var prop in proxy) { ... } Object.defineProperty(proxy,‘foo’, pd) Tuesday, September 28, 2010
  • 28. But not quite everything, either var proxy = Proxy.create(handler, proto); handler meta base proxy Tuesday, September 28, 2010
  • 29. But not quite everything, either var proxy = Proxy.create(handler, proto); handler meta base proxy === obj proxy Tuesday, September 28, 2010
  • 30. But not quite everything, either var proxy = Proxy.create(handler, proto); handler meta base proxy === obj Object.getPrototypeOf(proxy) => proto proxy proto Tuesday, September 28, 2010
  • 31. But not quite everything, either var proxy = Proxy.create(handler, proto); handler meta base proxy === obj Object.getPrototypeOf(proxy) => proto proxy proto proxy instanceof SomeFunction Tuesday, September 28, 2010
  • 32. But not quite everything, either var proxy = Proxy.create(handler, proto); handler meta base proxy === obj Object.getPrototypeOf(proxy) => proto proxy proto proxy instanceof SomeFunction typeof proxy => “object” Tuesday, September 28, 2010
  • 33. Full Handler API handler proxy Object.getOwnPropertyDescriptor(proxy) handler.getOwnPropertyDescriptor(name) Object.getPropertyDescriptor(proxy) handler.getPropertyDescriptor(name) Object.defineProperty(proxy,name,pd) handler.defineProperty(name, pd) Object.getOwnPropertyNames(proxy)  handler.getOwnPropertyNames() delete proxy.name handler.delete(name)  for (name in proxy) { ... }  handler.enumerate() Object.{freeze|seal|...}(proxy) handler.fix() name in proxy handler.has(name) ({}).hasOwnProperty.call(proxy, name) handler.hasOwn(name) receiver.name handler.get(receiver, name) receiver.name = val handler.set(receiver, name, val) Object.keys(proxy) handler.keys() for (name in proxy) { ... } handler.iterate() Tuesday, September 28, 2010
  • 34. Fundamental vs Derived Traps handler proxy Fundamental traps Object.getOwnPropertyDescriptor(proxy) handler.getOwnPropertyDescriptor(name) Object.getPropertyDescriptor(proxy) handler.getPropertyDescriptor(name) Object.defineProperty(proxy,name,pd) handler.defineProperty(name, pd) Object.getOwnPropertyNames(proxy)  handler.getOwnPropertyNames() delete proxy.name handler.delete(name)  for (name in proxy) { ... }  handler.enumerate() -> [string] Object.{freeze|seal|...}(proxy) handler.fix() Derived traps name in proxy handler.has(name) ({}).hasOwnProperty.call(proxy, name) handler.hasOwn(name) receiver.name handler.get(receiver, name) receiver.name = val handler.set(receiver, name, val) Object.keys(proxy) handler.keys() for (name in proxy) { ... } handler.iterate() -> iterator Tuesday, September 28, 2010
  • 35. Function Proxies JavaScript functions are objects. Additionally, they are also callable and constructible var call = function() { ... }; var construct = function() { ... }; var funproxy = Proxy.createFunction(handler, call, construct); handler call construct funproxy Tuesday, September 28, 2010
  • 36. Function Proxies JavaScript functions are objects. Additionally, they are also callable and constructible var call = function() { ... }; var construct = function() { ... }; var funproxy = Proxy.createFunction(handler, call, construct); call(1,2,3) handler call construct funproxy(1,2,3) funproxy Tuesday, September 28, 2010
  • 37. Function Proxies JavaScript functions are objects. Additionally, they are also callable and constructible var call = function() { ... }; var construct = function() { ... }; var funproxy = Proxy.createFunction(handler, call, construct); call(1,2,3) handler call construct construct(1,2,3) funproxy(1,2,3) new funproxy(1,2,3) funproxy Tuesday, September 28, 2010
  • 38. Function Proxies JavaScript functions are objects. Additionally, they are also callable and constructible var call = function() { ... }; var construct = function() { ... }; var funproxy = Proxy.createFunction(handler, call, construct); call(1,2,3) handler call construct construct(1,2,3) handler.get(funproxy,‘prototype’) funproxy(1,2,3) new funproxy(1,2,3) funproxy.prototype funproxy Tuesday, September 28, 2010
  • 39. Function Proxies JavaScript functions are objects. Additionally, they are also callable and constructible var call = function() { ... }; var construct = function() { ... }; var funproxy = Proxy.createFunction(handler, call, construct); call(1,2,3) handler call construct construct(1,2,3) handler.get(funproxy,‘prototype’) funproxy(1,2,3) new funproxy(1,2,3) funproxy.prototype funproxy typeof funproxy => “function” Tuesday, September 28, 2010
  • 40. Function Proxies JavaScript functions are objects. Additionally, they are also callable and constructible var call = function() { ... }; var construct = function() { ... }; var funproxy = Proxy.createFunction(handler, call, construct); call(1,2,3) handler call construct construct(1,2,3) handler.get(funproxy,‘prototype’) funproxy(1,2,3) new funproxy(1,2,3) funproxy.prototype funproxy typeof funproxy => “function” Object.getPrototypeOf(funproxy) => Function.prototype Tuesday, September 28, 2010
  • 41. Dilemma: Invoke vs Get+Call • Fundamental vs derived traps = tradeoff in performance (method allocation or caching) vs. consistency var p = Proxy.create({   get:    function(receiver, name) { ... },   invoke: function(receiver, name, args) { ... },   ... }); p.x; // get(p,'x') p.m(a); // invoke(p, 'm', [a]) • invoke can intercept arguments • but notably, JS methods can be extracted as functions and called later (functional FTW!) • breaks invariant o.m.call(o) <=> o.m() Tuesday, September 28, 2010
  • 42. Selective Interception meta base object Tuesday, September 28, 2010
  • 43. Selective Interception VM territory (C++) meta base object JavaScript territory Tuesday, September 28, 2010
  • 44. Selective Interception VM territory (C++) VM handler meta base object JavaScript territory Tuesday, September 28, 2010
  • 45. Selective Interception VM territory (C++) VM handler VM handler meta base host object object JavaScript territory Tuesday, September 28, 2010
  • 46. Selective Interception VM territory (C++) VM handler VM handler handler meta base host object object proxy JavaScript territory Tuesday, September 28, 2010
  • 47. Selective Interception VM territory (C++) VM handler VM handler handler meta base host object object proxy JavaScript territory Tuesday, September 28, 2010
  • 48. Selective Interception VM territory (C++) Self-hosted VM handler VM handler handler meta base host object object proxy JavaScript territory Tuesday, September 28, 2010
  • 49. Selective Interception VM territory (C++) Self-hosted VM handler VM handler handler meta base host object object proxy JavaScript territory Tuesday, September 28, 2010
  • 50. Example: no-op forwarding proxy handler function ForwardingHandler(obj) { this.target = obj; proxy target } ForwardingHandler.prototype = {   has: function(name) { return name in this.target; },   get: function(rcvr,name) { return this.target[name]; },   set: function(rcvr,name,val) { this.target[name]=val;return true; },   delete: function(name) { return delete this.target[name]; }   enumerate: function() {     var props = []; for (name in this.target) { props.push(name); }; return props;   }, ... } var proxy = Proxy.create(new ForwardingHandler(o),                          Object.getPrototypeOf(o)); Tuesday, September 28, 2010
  • 51. Example: counting property access function makeSimpleProfiler(target) { var forwarder = new ForwardingHandler(target); var count = Object.create(null); forwarder.get = function(rcvr, name) { count[name] = (count[name] || 0) + 1; return this.target[name]; }; return { proxy: Proxy.create(forwarder, Object.getPrototypeOf(target)), get stats() { return count; } } } Tuesday, September 28, 2010
  • 52. Example: counting property access function makeSimpleProfiler(target) { var forwarder = new ForwardingHandler(target); var count = Object.create(null); forwarder.get = function(rcvr, name) { count[name] = (count[name] || 0) + 1; return this.target[name]; }; return { proxy: Proxy.create(forwarder, Object.getPrototypeOf(target)), get stats() { return count; } } } var subject = { ... }; var profiler = makeSimpleProfiler(subject); runApp(profiler.proxy); display(profiler.stats); Tuesday, September 28, 2010
  • 53. Fixing a Proxy var proxy = Proxy.create(handler, proto); handler meta base proxy Tuesday, September 28, 2010
  • 54. Fixing a Proxy var proxy = Proxy.create(handler, proto); handler meta base Object.freeze(proxy) Object.seal(proxy) proxy Object.preventExtensions(proxy) Tuesday, September 28, 2010
  • 55. Fixing a Proxy var proxy = Proxy.create(handler, proto); var pdmap = handler.fix(); if (pdmap === undefined) throw TypeError(); handler become(proxy, Object.freeze( Object.create(proto, pdmap))); meta base Object.freeze(proxy) Object.seal(proxy) proxy Object.preventExtensions(proxy) Tuesday, September 28, 2010
  • 56. Fixing a Proxy var proxy = Proxy.create(handler, proto); var pdmap = handler.fix(); if (pdmap === undefined) throw TypeError(); handler become(proxy, Object.freeze( Object.create(proto, pdmap))); meta base Object.freeze(proxy) Object.seal(proxy) proxy Object.preventExtensions(proxy) fix Trapping Fixed Tuesday, September 28, 2010
  • 57. Fixing a Proxy var proxy = Proxy.create(handler, proto); var pdmap = handler.fix(); if (pdmap === undefined) throw TypeError(); become(proxy, Object.freeze( Object.create(proto, pdmap))); meta base Object.freeze(proxy) Object.seal(proxy) proxy Object.preventExtensions(proxy) fix Trapping Fixed Tuesday, September 28, 2010
  • 58. Meta-level Shifting handler proxy Object.getOwnPropertyDescriptor(proxy) handler.getOwnPropertyDescriptor(name) Object.getPropertyDescriptor(proxy) handler.getPropertyDescriptor(name) Object.defineProperty(proxy,name,pd) handler.defineProperty(name, pd) Object.getOwnPropertyNames(proxy)  handler.getOwnPropertyNames() delete proxy.name handler.delete(name)  for (name in proxy) { ... }  handler.enumerate() Object.{freeze|seal|...}(proxy) handler.fix() name in proxy handler.has(name) ({}).hasOwnProperty.call(proxy, name) handler.hasOwn(name) receiver.name handler.get(receiver, name) receiver.name = val handler.set(receiver, name, val) Object.keys(proxy) handler.keys() for (name in proxy) { ... }  handler.iterate() base-level: many operations meta-level: all operations reified as on objects invocations of traps Tuesday, September 28, 2010
  • 59. Meta-level Shifting a proxy whose μhandler handler is a proxy handler handler.getOwnPropertyDescriptor(name) μhandler.get(handler, ‘getOwnP..’)(name) handler.getPropertyDescriptor(name) μhandler.get(handler, ‘getProp..’)(name) handler.defineOwnProperty(name, pd) μhandler.get(handler, ‘define...’)(name,pd) handler.delete(name)  μhandler.get(handler, ‘delete’)(name) handler.getOwnPropertyNames() μhandler.get(handler, ‘getOwnP..’)() handler.enumerate() μhandler.get(handler, ‘enumerate’)() handler.fix() μhandler.get(handler, ‘fix’)() handler.has(name) μhandler.get(handler, ‘has’)(name) handler.hasOwn(name) μhandler.get(handler, ‘hasOwn’)(name) handler.get(receiver, name) μhandler.get(handler, ‘get’)(receiver,name) handler.set(receiver, name, val) μhandler.get(handler, ‘set’)(receiver,name,val) handler.keys() μhandler.get(handler, ‘keys’)() handler.iterate() μhandler.get(handler, ‘iterate’)() meta-level: all operations reified as meta-meta-level: all operations invocations of traps reified as invocations of ‘get’ trap Tuesday, September 28, 2010
  • 60. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 61. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 62. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 63. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 64. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 65. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 66. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 67. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 68. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 69. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 70. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 71. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 72. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 73. Example: Membranes • Firefox security wrappers (anti-XSS, XUL, etc.) • Google Caja: capability-secure subset • Object-capability model: an object is powerless unless given a reference to other objects • References can be made revocable through a membrane Tuesday, September 28, 2010
  • 74. Example: Membranes function makeSimpleMembrane(initTarget) {   var enabled = true; } Tuesday, September 28, 2010
  • 75. Example: Membranes function makeSimpleMembrane(initTarget) {   var enabled = true;   return { wrapper: wrap(initTarget), revoke: function() { enabled = false; } }; } Tuesday, September 28, 2010
  • 76. Example: Membranes function makeSimpleMembrane(initTarget) {   var enabled = true;   function wrap(target) {     if (Object.isPrimitive(target)) { return target; }     var baseHandler = new ForwardingHandler(target);     var revokeHandler = Proxy.create({       get: function(rcvr, name) { return wrapFunction(baseHandler[name]); }     });   }   return { wrapper: wrap(initTarget), revoke: function() { enabled = false; } }; } Tuesday, September 28, 2010
  • 77. Example: Membranes function makeSimpleMembrane(initTarget) {   var enabled = true;   function wrap(target) {     if (Object.isPrimitive(target)) { return target; }     var baseHandler = new ForwardingHandler(target);     var revokeHandler = Proxy.create({       get: function(rcvr, name) { return wrapFunction(baseHandler[name]); }     }); if (typeof target === “function”) { return Proxy.createFunction(revokeHandler, wrapFunction(target)); }     return Proxy.create(revokeHandler, wrap(Object.getPrototypeOf(target)));   }   return { wrapper: wrap(initTarget), revoke: function() { enabled = false; } }; } Tuesday, September 28, 2010
  • 78. Example: Membranes function makeSimpleMembrane(initTarget) {   var enabled = true; function wrapFunction(f) {     return function() { // variable-argument function if (!enabled) { throw new Error("revoked"); }      return wrap(f.apply(wrap(this), arguments.map(wrap))); } }   function wrap(target) {     if (Object.isPrimitive(target)) { return target; }     var baseHandler = new ForwardingHandler(target);     var revokeHandler = Proxy.create({       get: function(rcvr, name) { return wrapFunction(baseHandler[name]); }     }); if (typeof target === “function”) { return Proxy.createFunction(revokeHandler, wrapFunction(target)); }     return Proxy.create(revokeHandler, wrap(Object.getPrototypeOf(target)));   }   return { wrapper: wrap(initTarget), revoke: function() { enabled = false; } }; } Tuesday, September 28, 2010
  • 79. Prior Work handler meta base proxy Tuesday, September 28, 2010
  • 80. Prior Work handler mirror ProxyHandler InvocationHandler meta base proxy mirage proxy java.lang.reflect.Proxy Tuesday, September 28, 2010
  • 81. Prior Work handler mirror ProxyHandler InvocationHandler meta base proxy mirage proxy java.lang.reflect.Proxy # traps 13 30 3 1 Tuesday, September 28, 2010
  • 82. Making JavaScript Extensible • Extending JavaScript today: “Host objects” (the IE DOM; anything implemented in C++) • Proxies are sufficiently powerful to emulate most of the behavior of host objects in JavaScript itself • Two possible avenues to close the gap: • Make proxies even more powerful • Make host objects only as powerful as proxies Tuesday, September 28, 2010
  • 83. Status • Presented at ECMA TC-39 meetings • Approved for inclusion in ES-Harmony • http://wiki.ecmascript.org/doku.php? id=harmony:proxies • In Firefox 4 already, thanks to Andreas Gal! • The basis of all of Gecko’s security wrappers • Used by Zaphod (Narcissus as JS engine add-on, source at http://github.com/taustin/Zaphod/) Tuesday, September 28, 2010
  • 84. Lessons for Web Standards • Standards need savvy academic research • Standards must evolve quickly on the Web • They can’t evolve without prototype trials • These experiments need tons of user-testing • To reach users at scale, prototypes must ship • Ecma TC39 committed to prototyping specs before finalizing standards • Committee members work together, no blind-siding, to uphold Harmony (it’s social!) Tuesday, September 28, 2010
  • 87. Proxies: Summary • Proxies enable: • Generic wrappers: access control, profiling, adaptors, test injection, etc. • Virtual objects: persistent objects, remote objects, emulated host objects, ... • API: • Robust: stratified, not all operations intercepted • Secure: can’t trap non-proxy or fixed objects • Performance: no overhead for non-proxy objects Tuesday, September 28, 2010
  • 88. Conclusions • ES5 provides new meta-programming APIs • ES-Harmony Proxies: robust dynamic meta- programming for virtual objects, wrappers • Proxies help put developers in control of extending JavaScript, instead of Ecma TC39 • JavaScript: the Revenge of Smalltalk! Tuesday, September 28, 2010