12c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
22c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// Redistribution and use in source and binary forms, with or without
32c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// modification, are permitted provided that the following conditions are
42c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// met:
52c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//
62c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//     * Redistributions of source code must retain the above copyright
72c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//       notice, this list of conditions and the following disclaimer.
82c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//     * Redistributions in binary form must reproduce the above
92c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//       copyright notice, this list of conditions and the following
102c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//       disclaimer in the documentation and/or other materials provided
112c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//       with the distribution.
122c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//     * Neither the name of Google Inc. nor the names of its
132c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//       contributors may be used to endorse or promote products derived
142c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//       from this software without specific prior written permission.
152c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org//
162c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
288640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org// Flags: --harmony --harmony-proxies
292c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
302c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
312c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// A simple no-op handler. Adapted from:
322c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#examplea_no-op_forwarding_proxy
332c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
342c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgfunction createHandler(obj) {
352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  return {
362c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    getOwnPropertyDescriptor: function(name) {
372c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var desc = Object.getOwnPropertyDescriptor(obj, name);
382c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      if (desc !== undefined) desc.configurable = true;
392c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return desc;
402c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
412c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    getPropertyDescriptor: function(name) {
422c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var desc = Object.getOwnPropertyDescriptor(obj, name);
432c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      //var desc = Object.getPropertyDescriptor(obj, name);  // not in ES5
442c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      if (desc !== undefined) desc.configurable = true;
452c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return desc;
462c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
472c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    getOwnPropertyNames: function() {
482c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return Object.getOwnPropertyNames(obj);
492c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
502c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    getPropertyNames: function() {
512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return Object.getOwnPropertyNames(obj);
522c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      //return Object.getPropertyNames(obj);  // not in ES5
532c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
542c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    defineProperty: function(name, desc) {
552c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      Object.defineProperty(obj, name, desc);
562c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
572c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    delete: function(name) {
582c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return delete obj[name];
592c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
602c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    fix: function() {
612c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      if (Object.isFrozen(obj)) {
622c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        var result = {};
632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        Object.getOwnPropertyNames(obj).forEach(function(name) {
642c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          result[name] = Object.getOwnPropertyDescriptor(obj, name);
652c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        });
662c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return result;
672c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
682c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      // As long as obj is not frozen, the proxy won't allow itself to be fixed
692c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return undefined; // will cause a TypeError to be thrown
702c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    has: function(name) { return name in obj; },
722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
732c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    get: function(receiver, name) { return obj[name]; },
742c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    set: function(receiver, name, val) {
75486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      obj[name] = val;  // bad behavior when set fails in sloppy mode
762c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return true;
772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
782c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    enumerate: function() {
792c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var result = [];
802c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      for (var name in obj) { result.push(name); };
812c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return result;
822c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    },
832c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    keys: function() { return Object.keys(obj); }
842c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  };
852c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org}
862c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
872c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
882c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
892c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// Auxiliary definitions enabling tracking of object identity in output.
902c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
912c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar objectMap = new WeakMap;
922c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar objectCounter = 0;
932c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
942c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgfunction registerObject(x, s) {
952c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  if (x === Object(x) && !objectMap.has(x))
962c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    objectMap.set(x, ++objectCounter + (s == undefined ? "" : ":" + s));
972c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org}
982c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
992c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgregisterObject(this, "global");
1002c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgregisterObject(Object.prototype, "Object.prototype");
1012c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1022c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgfunction str(x) {
1032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  if (x === Object(x)) return "[" + typeof x + " " + objectMap.get(x) + "]";
1042c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  if (typeof x == "string") return "\"" + x + "\"";
1052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  return "" + x;
1062c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org}
1072c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1082c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1092c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1102c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// A simple membrane. Adapted from:
1112c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#a_simple_membrane
1122c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1132c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgfunction createSimpleMembrane(target) {
1142c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  var enabled = true;
1152c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1162c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  function wrap(obj) {
1172c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    registerObject(obj);
1182c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    print("wrap enter", str(obj));
1192c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    try {
1202c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var x = wrap2(obj);
1212c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      registerObject(x, "wrapped");
1222c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("wrap exit", str(obj), "as", str(x));
1232c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return x;
1242c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    } catch(e) {
1252c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("wrap exception", str(e));
1262c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      throw e;
1272c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
1282c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  }
1292c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1302c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  function wrap2(obj) {
1312c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (obj !== Object(obj)) {
1322c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return obj;
1332c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
1342c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    function wrapCall(fun, that, args) {
1362c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      registerObject(that);
1372c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("wrapCall enter", fun, str(that));
1382c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      try {
1392c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        var x = wrapCall2(fun, that, args);
1402c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("wrapCall exit", fun, str(that), "returning", str(x));
1412c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return x;
1422c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      } catch(e) {
1432c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("wrapCall exception", fun, str(that), str(e));
1442c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        throw e;
1452c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
1462c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
1472c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1482c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    function wrapCall2(fun, that, args) {
1492c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      if (!enabled) { throw new Error("disabled"); }
1502c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      try {
1512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return wrap(fun.apply(that, Array.prototype.map.call(args, wrap)));
1522c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      } catch (e) {
1532c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        throw wrap(e);
1542c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
1552c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
1562c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1572c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var baseHandler = createHandler(obj);
1582c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var handler = Proxy.create(Object.freeze({
1592c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      get: function(receiver, name) {
1602c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return function() {
1612c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          var arg = (name === "get" || name == "set") ? arguments[1] : "";
1622c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          print("handler enter", name, arg);
1632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          var x = wrapCall(baseHandler[name], baseHandler, arguments);
1642c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          print("handler exit", name, arg, "returning", str(x));
1652c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          return x;
1662c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        }
1672c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
1682c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }));
1692c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    registerObject(baseHandler, "basehandler");
1702c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    registerObject(handler, "handler");
1712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (typeof obj === "function") {
1732c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      function callTrap() {
1742c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("call trap enter", str(obj), str(this));
1752c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        var x = wrapCall(obj, wrap(this), arguments);
1762c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("call trap exit", str(obj), str(this), "returning", str(x));
1772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return x;
1782c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
1792c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      function constructTrap() {
1802c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        if (!enabled) { throw new Error("disabled"); }
1812c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        try {
1822c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          function forward(args) { return obj.apply(this, args) }
1832c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          return wrap(new forward(Array.prototype.map.call(arguments, wrap)));
1842c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        } catch (e) {
1852c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          throw wrap(e);
1862c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        }
1872c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
1882c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return Proxy.createFunction(handler, callTrap, constructTrap);
1892c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    } else {
1902c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var prototype = wrap(Object.getPrototypeOf(obj));
1912c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return Proxy.create(handler, prototype);
1922c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
1932c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  }
1942c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
1952c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  var gate = Object.freeze({
1962c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    enable: function() { enabled = true; },
1972c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    disable: function() { enabled = false; }
1982c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  });
1992c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2002c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  return Object.freeze({
2012c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    wrapper: wrap(target),
2022c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    gate: gate
2032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  });
2042c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org}
2052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2062c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2072c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar o = {
2082c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  a: 6,
2092c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  b: {bb: 8},
2102c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  f: function(x) { return x },
2112c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  g: function(x) { return x.a },
2122c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  h: function(x) { this.q = x }
2132c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org};
2142c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgo[2] = {c: 7};
2152c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar m = createSimpleMembrane(o);
2162c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar w = m.wrapper;
2172c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgprint("o =", str(o))
2182c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgprint("w =", str(w));
2192c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2202c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar f = w.f;
2212c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar x = f(66);
2222c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar x = f({a: 1});
2232c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar x = w.f({a: 1});
2242c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar a = x.a;
2252c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(6, w.a);
2262c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(8, w.b.bb);
2272c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, w[2]["c"]);
2282c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(undefined, w.c);
2292c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(1, w.f(1));
2302c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(1, w.f({a: 1}).a);
2312c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(2, w.g({a: 2}));
2322c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, (w.r = {a: 3}).a);
2332c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, w.r.a);
2342c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, o.r.a);
2352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgw.h(3);
2362c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, w.q);
2372c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, o.q);
2382c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(4, (new w.h(4)).q);
2392c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2402c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wb = w.b;
2412c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wr = w.r;
2422c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wf = w.f;
2432c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wf3 = w.f(3);
2442c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wfx = w.f({a: 6});
2452c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wgx = w.g({a: {aa: 7}});
2462c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wh4 = new w.h(4);
2472c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgm.gate.disable();
2482c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, wf3);
2492c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.a }, Error);
2502c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.r }, Error);
2512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.r = {a: 4} }, Error);
2522c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { o.r.a }, Error);
2532c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals("object", typeof o.r);
2542c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, (o.r = {a: 5}).a);
2552c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, o.r.a);
2562c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w[1] }, Error);
2572c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.c }, Error);
2582c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wb.bb }, Error);
2592c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wr.a }, Error);
2602c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wf(4) }, Error);
2612c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wfx.a }, Error);
2622c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wgx.aa }, Error);
2632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wh4.q }, Error);
2642c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2652c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgm.gate.enable();
2662c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(6, w.a);
2672c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, w.r.a);
2682c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, o.r.a);
2692c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, w.r = 7);
2702c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, w.r);
2712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, o.r);
2722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(8, w.b.bb);
2732c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, w[2]["c"]);
2742c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(undefined, w.c);
2752c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(8, wb.bb);
2762c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, wr.a);
2772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(4, wf(4));
2782c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, wf3);
2792c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(6, wfx.a);
2802c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, wgx.aa);
2812c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(4, wh4.q);
2822c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2832c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2842c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// An identity-preserving membrane. Adapted from:
2852c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving_membrane
2862c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2872c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgfunction createMembrane(wetTarget) {
288d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  var wet2dry = new WeakMap();
289d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  var dry2wet = new WeakMap();
2902c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
2912c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  function asDry(obj) {
2922c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    registerObject(obj)
2932c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    print("asDry enter", str(obj))
2942c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    try {
2952c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var x = asDry2(obj);
2962c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      registerObject(x, "dry");
2972c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("asDry exit", str(obj), "as", str(x));
2982c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return x;
2992c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    } catch(e) {
3002c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("asDry exception", str(e));
3012c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      throw e;
3022c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
3032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  }
3042c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  function asDry2(wet) {
3052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (wet !== Object(wet)) {
3062c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      // primitives provide only irrevocable knowledge, so don't
3072c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      // bother wrapping it.
3082c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return wet;
3092c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
3102c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var dryResult = wet2dry.get(wet);
3112c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (dryResult) { return dryResult; }
3122c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
3132c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var wetHandler = createHandler(wet);
3142c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var dryRevokeHandler = Proxy.create(Object.freeze({
3152c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      get: function(receiver, name) {
3162c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return function() {
3172c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          var arg = (name === "get" || name == "set") ? arguments[1] : "";
3182c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          print("dry handler enter", name, arg);
3192c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          var optWetHandler = dry2wet.get(dryRevokeHandler);
3202c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          try {
3212c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            var x = asDry(optWetHandler[name].apply(
3222c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org              optWetHandler, Array.prototype.map.call(arguments, asWet)));
3232c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            print("dry handler exit", name, arg, "returning", str(x));
3242c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            return x;
3252c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          } catch (eWet) {
3262c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            var x = asDry(eWet);
3272c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            print("dry handler exception", name, arg, "throwing", str(x));
3282c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            throw x;
3292c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          }
3302c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        };
3312c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
3322c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }));
3332c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    dry2wet.set(dryRevokeHandler, wetHandler);
3342c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
3352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (typeof wet === "function") {
3362c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      function callTrap() {
3372c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("dry call trap enter", str(this));
3382c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        var x = asDry(wet.apply(
3392c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          asWet(this), Array.prototype.map.call(arguments, asWet)));
3402c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("dry call trap exit", str(this), "returning", str(x));
3412c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return x;
3422c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
3432c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      function constructTrap() {
3442c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        function forward(args) { return wet.apply(this, args) }
3452c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return asDry(new forward(Array.prototype.map.call(arguments, asWet)));
3462c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
3472c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      dryResult =
3482c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        Proxy.createFunction(dryRevokeHandler, callTrap, constructTrap);
3492c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    } else {
3502c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      dryResult =
3512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        Proxy.create(dryRevokeHandler, asDry(Object.getPrototypeOf(wet)));
3522c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
3532c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    wet2dry.set(wet, dryResult);
3542c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    dry2wet.set(dryResult, wet);
3552c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    return dryResult;
3562c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  }
3572c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
3582c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  function asWet(obj) {
3592c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    registerObject(obj)
3602c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    print("asWet enter", str(obj))
3612c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    try {
3622c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      var x = asWet2(obj)
3632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      registerObject(x, "wet")
3642c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("asWet exit", str(obj), "as", str(x))
3652c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return x
3662c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    } catch(e) {
3672c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      print("asWet exception", str(e))
3682c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      throw e
3692c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
3702c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  }
3712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  function asWet2(dry) {
3722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (dry !== Object(dry)) {
3732c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      // primitives provide only irrevocable knowledge, so don't
3742c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      // bother wrapping it.
3752c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      return dry;
3762c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
3772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var wetResult = dry2wet.get(dry);
3782c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (wetResult) { return wetResult; }
3792c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
3802c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var dryHandler = createHandler(dry);
3812c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    var wetRevokeHandler = Proxy.create(Object.freeze({
3822c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      get: function(receiver, name) {
3832c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return function() {
3842c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          var arg = (name === "get" || name == "set") ? arguments[1] : "";
3852c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          print("wet handler enter", name, arg);
3862c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          var optDryHandler = wet2dry.get(wetRevokeHandler);
3872c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          try {
3882c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            var x = asWet(optDryHandler[name].apply(
3892c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org              optDryHandler, Array.prototype.map.call(arguments, asDry)));
3902c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            print("wet handler exit", name, arg, "returning", str(x));
3912c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            return x;
3922c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          } catch (eDry) {
3932c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            var x = asWet(eDry);
3942c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            print("wet handler exception", name, arg, "throwing", str(x));
3952c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org            throw x;
3962c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          }
3972c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        };
3982c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
3992c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }));
4002c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    wet2dry.set(wetRevokeHandler, dryHandler);
4012c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4022c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    if (typeof dry === "function") {
4032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      function callTrap() {
4042c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("wet call trap enter", str(this));
4052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        var x = asWet(dry.apply(
4062c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org          asDry(this), Array.prototype.map.call(arguments, asDry)));
4072c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        print("wet call trap exit", str(this), "returning", str(x));
4082c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return x;
4092c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
4102c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      function constructTrap() {
4112c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        function forward(args) { return dry.apply(this, args) }
4122c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        return asWet(new forward(Array.prototype.map.call(arguments, asDry)));
4132c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      }
4142c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      wetResult =
4152c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        Proxy.createFunction(wetRevokeHandler, callTrap, constructTrap);
4162c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    } else {
4172c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      wetResult =
4182c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        Proxy.create(wetRevokeHandler, asWet(Object.getPrototypeOf(dry)));
4192c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
4202c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    dry2wet.set(dry, wetResult);
4212c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    wet2dry.set(wetResult, dry);
4222c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    return wetResult;
4232c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  }
4242c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4252c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  var gate = Object.freeze({
4262c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    revoke: function() {
4272c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      dry2wet = wet2dry = Object.freeze({
4282c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        get: function(key) { throw new Error("revoked"); },
4292c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org        set: function(key, val) { throw new Error("revoked"); }
4302c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      });
4312c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    }
4322c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  });
4332c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4342c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  return Object.freeze({ wrapper: asDry(wetTarget), gate: gate });
4352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org}
4362c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4372c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4382c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar receiver
4392c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar argument
4402c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar o = {
4412c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  a: 6,
4422c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  b: {bb: 8},
4432c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  f: function(x) { receiver = this; argument = x; return x },
4442c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  g: function(x) { receiver = this; argument = x; return x.a },
4452c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  h: function(x) { receiver = this; argument = x; this.q = x },
4462c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  s: function(x) { receiver = this; argument = x; this.x = {y: x}; return this }
4472c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org}
4482c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgo[2] = {c: 7}
4492c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar m = createMembrane(o)
4502c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar w = m.wrapper
4512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgprint("o =", str(o))
4522c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgprint("w =", str(w))
4532c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4542c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar f = w.f
4552c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar x = f(66)
4562c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar x = f({a: 1})
4572c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar x = w.f({a: 1})
4582c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar a = x.a
4592c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(6, w.a)
4602c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(8, w.b.bb)
4612c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, w[2]["c"])
4622c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(undefined, w.c)
4632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(1, w.f(1))
4642c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, receiver)
4652c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(1, w.f({a: 1}).a)
4662c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, receiver)
4672c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(2, w.g({a: 2}))
4682c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, receiver)
4692c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(w, w.f(w))
4702c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, receiver)
4712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, argument)
4722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, w.f(o))
4732c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, receiver)
4742c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org// Note that argument !== o, since o isn't dry, so gets wrapped wet again.
4752c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, (w.r = {a: 3}).a)
4762c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, w.r.a)
4772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, o.r.a)
4782c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgw.h(3)
4792c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, w.q)
4802c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, o.q)
4812c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(4, (new w.h(4)).q)
4822c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, w.s(5).x.y)
4832c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertSame(o, receiver)
4842c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
4852c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wb = w.b
4862c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wr = w.r
4872c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wf = w.f
4882c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wf3 = w.f(3)
4892c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wfx = w.f({a: 6})
4902c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wgx = w.g({a: {aa: 7}})
4912c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar wh4 = new w.h(4)
4922c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar ws5 = w.s(5)
4932c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgvar ws5x = ws5.x
4942c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgm.gate.revoke()
4952c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, wf3)
4962c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.a }, Error)
4972c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.r }, Error)
4982c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.r = {a: 4} }, Error)
4992c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { o.r.a }, Error)
5002c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals("object", typeof o.r)
5012c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, (o.r = {a: 5}).a)
5022c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(5, o.r.a)
5032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w[1] }, Error)
5042c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { w.c }, Error)
5052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wb.bb }, Error)
5062c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(3, wr.a)
5072c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wf(4) }, Error)
5082c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(6, wfx.a)
5092c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertEquals(7, wgx.aa)
5102c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { wh4.q }, Error)
5112c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { ws5.x }, Error)
5122c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.orgassertThrows(function() { ws5x.y }, Error)
513