1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28"use strict"; 29 30global.Proxy = new $Object(); 31 32var $Proxy = global.Proxy 33 34$Proxy.create = function(handler, proto) { 35 if (!IS_SPEC_OBJECT(handler)) 36 throw MakeTypeError("handler_non_object", ["create"]) 37 if (IS_UNDEFINED(proto)) 38 proto = null 39 else if (!(IS_SPEC_OBJECT(proto) || proto === null)) 40 throw MakeTypeError("proto_non_object", ["create"]) 41 return %CreateJSProxy(handler, proto) 42} 43 44$Proxy.createFunction = function(handler, callTrap, constructTrap) { 45 if (!IS_SPEC_OBJECT(handler)) 46 throw MakeTypeError("handler_non_object", ["create"]) 47 if (!IS_SPEC_FUNCTION(callTrap)) 48 throw MakeTypeError("trap_function_expected", ["createFunction", "call"]) 49 if (IS_UNDEFINED(constructTrap)) { 50 constructTrap = DerivedConstructTrap(callTrap) 51 } else if (IS_SPEC_FUNCTION(constructTrap)) { 52 // Make sure the trap receives 'undefined' as this. 53 var construct = constructTrap 54 constructTrap = function() { 55 return %Apply(construct, void 0, arguments, 0, %_ArgumentsLength()); 56 } 57 } else { 58 throw MakeTypeError("trap_function_expected", 59 ["createFunction", "construct"]) 60 } 61 return %CreateJSFunctionProxy( 62 handler, callTrap, constructTrap, $Function.prototype) 63} 64 65 66 67//////////////////////////////////////////////////////////////////////////////// 68// Builtins 69//////////////////////////////////////////////////////////////////////////////// 70 71function DerivedConstructTrap(callTrap) { 72 return function() { 73 var proto = this.prototype 74 if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype 75 var obj = new $Object() 76 obj.__proto__ = proto 77 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength()); 78 return IS_SPEC_OBJECT(result) ? result : obj 79 } 80} 81 82function DelegateCallAndConstruct(callTrap, constructTrap) { 83 return function() { 84 return %Apply(%_IsConstructCall() ? constructTrap : callTrap, 85 this, arguments, 0, %_ArgumentsLength()) 86 } 87} 88 89function DerivedGetTrap(receiver, name) { 90 var desc = this.getPropertyDescriptor(name) 91 if (IS_UNDEFINED(desc)) { return desc } 92 if ('value' in desc) { 93 return desc.value 94 } else { 95 if (IS_UNDEFINED(desc.get)) { return desc.get } 96 // The proposal says: desc.get.call(receiver) 97 return %_CallFunction(receiver, desc.get) 98 } 99} 100 101function DerivedSetTrap(receiver, name, val) { 102 var desc = this.getOwnPropertyDescriptor(name) 103 if (desc) { 104 if ('writable' in desc) { 105 if (desc.writable) { 106 desc.value = val 107 this.defineProperty(name, desc) 108 return true 109 } else { 110 return false 111 } 112 } else { // accessor 113 if (desc.set) { 114 // The proposal says: desc.set.call(receiver, val) 115 %_CallFunction(receiver, val, desc.set) 116 return true 117 } else { 118 return false 119 } 120 } 121 } 122 desc = this.getPropertyDescriptor(name) 123 if (desc) { 124 if ('writable' in desc) { 125 if (desc.writable) { 126 // fall through 127 } else { 128 return false 129 } 130 } else { // accessor 131 if (desc.set) { 132 // The proposal says: desc.set.call(receiver, val) 133 %_CallFunction(receiver, val, desc.set) 134 return true 135 } else { 136 return false 137 } 138 } 139 } 140 this.defineProperty(name, { 141 value: val, 142 writable: true, 143 enumerable: true, 144 configurable: true}); 145 return true; 146} 147 148function DerivedHasTrap(name) { 149 return !!this.getPropertyDescriptor(name) 150} 151 152function DerivedHasOwnTrap(name) { 153 return !!this.getOwnPropertyDescriptor(name) 154} 155 156function DerivedKeysTrap() { 157 var names = this.getOwnPropertyNames() 158 var enumerableNames = [] 159 for (var i = 0, count = 0; i < names.length; ++i) { 160 var name = names[i] 161 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name)) 162 if (!IS_UNDEFINED(desc) && desc.enumerable) { 163 enumerableNames[count++] = names[i] 164 } 165 } 166 return enumerableNames 167} 168 169function DerivedEnumerateTrap() { 170 var names = this.getPropertyNames() 171 var enumerableNames = [] 172 for (var i = 0, count = 0; i < names.length; ++i) { 173 var name = names[i] 174 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name)) 175 if (!IS_UNDEFINED(desc) && desc.enumerable) { 176 enumerableNames[count++] = names[i] 177 } 178 } 179 return enumerableNames 180} 181 182function ProxyEnumerate(proxy) { 183 var handler = %GetHandler(proxy) 184 if (IS_UNDEFINED(handler.enumerate)) { 185 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0) 186 } else { 187 return ToStringArray(handler.enumerate(), "enumerate") 188 } 189} 190