1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Flags: --harmony-proxies --strong-mode 6 7// Forwarding proxies adapted from proposal definition 8function handlerMaker1(obj) { 9 return { 10 getPropertyDescriptor: function(name) { 11 var desc; 12 var searchObj = obj; 13 while (desc === undefined && searchObj != null) { 14 desc = Object.getOwnPropertyDescriptor(searchObj, name); 15 searchObj = searchObj.__proto__; 16 } 17 // a trapping proxy's properties must always be configurable 18 if (desc !== undefined) { desc.configurable = true; } 19 return desc; 20 }, 21 fix: function() { 22 if (Object.isFrozen(obj)) { 23 var result = {}; 24 Object.getOwnPropertyNames(obj).forEach(function(name) { 25 result[name] = Object.getOwnPropertyDescriptor(obj, name); 26 }); 27 return result; 28 } 29 // As long as obj is not frozen, the proxy won't allow itself to be fixed 30 return undefined; // will cause a TypeError to be thrown 31 } 32 }; 33} 34function handlerMaker2(obj) { 35 return { 36 get: function(receiver, name) { 37 return obj[name]; 38 }, 39 fix: function() { 40 if (Object.isFrozen(obj)) { 41 var result = {}; 42 Object.getOwnPropertyNames(obj).forEach(function(name) { 43 result[name] = Object.getOwnPropertyDescriptor(obj, name); 44 }); 45 return result; 46 } 47 // As long as obj is not frozen, the proxy won't allow itself to be fixed 48 return undefined; // will cause a TypeError to be thrown 49 } 50 }; 51} 52var baseObj = {}; 53var proxy1 = new Proxy({}, handlerMaker1(baseObj)); 54var proxy2 = new Proxy({}, handlerMaker2(baseObj)); 55var childObj1 = { __proto__: proxy1 }; 56var childObj2 = { __proto__: proxy2 }; 57var childObjAccessor1 = { set foo(_){}, set "1"(_){}, __proto__: proxy1 }; 58var childObjAccessor2 = { set foo(_){}, set "1"(_){}, __proto__: proxy2 }; 59 60(function() { 61 "use strong"; 62 // TODO(conradw): These asserts are sanity checking V8's proxy implementation. 63 // Strong mode semantics for ES6 proxies still need to be explored. 64 assertDoesNotThrow(function(){proxy1.foo}); 65 assertDoesNotThrow(function(){proxy1[1]}); 66 assertDoesNotThrow(function(){proxy2.foo}); 67 assertDoesNotThrow(function(){proxy2[1]}); 68 assertDoesNotThrow(function(){childObj1.foo}); 69 assertDoesNotThrow(function(){childObj1[1]}); 70 assertDoesNotThrow(function(){childObj2.foo}); 71 assertDoesNotThrow(function(){childObj2[1]}); 72 assertThrows(function(){baseObj.foo}, TypeError); 73 assertThrows(function(){baseObj[1]}, TypeError); 74 assertThrows(function(){childObjAccessor1.foo}, TypeError); 75 assertThrows(function(){childObjAccessor1[1]}, TypeError); 76 assertThrows(function(){childObjAccessor2.foo}, TypeError); 77 assertThrows(function(){childObjAccessor2[1]}, TypeError); 78 79 // Once the proxy is no longer trapping, property access should have strong 80 // semantics. 81 Object.freeze(baseObj); 82 83 // TODO(neis): Reenable once proxies properly support freeze. 84 // 85 // Object.freeze(proxy1); 86 // assertThrows(function(){proxy1.foo}, TypeError); 87 // assertThrows(function(){proxy1[1]}, TypeError); 88 // assertThrows(function(){childObj1.foo}, TypeError); 89 // assertThrows(function(){childObj1[1]}, TypeError); 90 // assertThrows(function(){childObjAccessor1.foo}, TypeError); 91 // assertThrows(function(){childObjAccessor1[1]}, TypeError); 92 // 93 // Object.freeze(proxy2); 94 // assertThrows(function(){proxy2.foo}, TypeError); 95 // assertThrows(function(){proxy2[1]}, TypeError); 96 // assertThrows(function(){childObj2.foo}, TypeError); 97 // assertThrows(function(){childObj2[1]}, TypeError); 98 // assertThrows(function(){childObjAccessor2.foo}, TypeError); 99 // assertThrows(function(){childObjAccessor2[1]}, TypeError); 100})(); 101