| OLD | NEW |
| (Empty) |
| 1 // Copyright 2011 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 (function(global, utils) { | |
| 6 | |
| 7 "use strict"; | |
| 8 | |
| 9 %CheckIsBootstrapping(); | |
| 10 | |
| 11 // ---------------------------------------------------------------------------- | |
| 12 // Imports | |
| 13 | |
| 14 var GlobalFunction = global.Function; | |
| 15 var GlobalObject = global.Object; | |
| 16 | |
| 17 var ToNameArray; | |
| 18 | |
| 19 utils.Import(function(from) { | |
| 20 ToNameArray = from.ToNameArray; | |
| 21 }); | |
| 22 | |
| 23 //---------------------------------------------------------------------------- | |
| 24 | |
| 25 function ProxyCreate(handler, proto) { | |
| 26 if (!IS_SPEC_OBJECT(handler)) | |
| 27 throw MakeTypeError(kProxyHandlerNonObject, "create") | |
| 28 if (IS_UNDEFINED(proto)) | |
| 29 proto = null | |
| 30 else if (!(IS_SPEC_OBJECT(proto) || IS_NULL(proto))) | |
| 31 throw MakeTypeError(kProxyProtoNonObject) | |
| 32 return %CreateJSProxy(handler, proto) | |
| 33 } | |
| 34 | |
| 35 function ProxyCreateFunction(handler, callTrap, constructTrap) { | |
| 36 if (!IS_SPEC_OBJECT(handler)) | |
| 37 throw MakeTypeError(kProxyHandlerNonObject, "createFunction") | |
| 38 if (!IS_CALLABLE(callTrap)) | |
| 39 throw MakeTypeError(kProxyTrapFunctionExpected, "call") | |
| 40 if (IS_UNDEFINED(constructTrap)) { | |
| 41 constructTrap = DerivedConstructTrap(callTrap) | |
| 42 } else if (IS_CALLABLE(constructTrap)) { | |
| 43 // Make sure the trap receives 'undefined' as this. | |
| 44 var construct = constructTrap | |
| 45 constructTrap = function() { | |
| 46 return %Apply(construct, UNDEFINED, arguments, 0, %_ArgumentsLength()); | |
| 47 } | |
| 48 } else { | |
| 49 throw MakeTypeError(kProxyTrapFunctionExpected, "construct") | |
| 50 } | |
| 51 return %CreateJSFunctionProxy( | |
| 52 handler, callTrap, constructTrap, GlobalFunction.prototype) | |
| 53 } | |
| 54 | |
| 55 // ------------------------------------------------------------------- | |
| 56 // Proxy Builtins | |
| 57 | |
| 58 function DerivedConstructTrap(callTrap) { | |
| 59 return function() { | |
| 60 var proto = this.prototype | |
| 61 if (!IS_SPEC_OBJECT(proto)) proto = GlobalObject.prototype | |
| 62 var obj = { __proto__: proto }; | |
| 63 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength()); | |
| 64 return IS_SPEC_OBJECT(result) ? result : obj | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 function DelegateCallAndConstruct(callTrap, constructTrap) { | |
| 69 return function() { | |
| 70 return %Apply(%_IsConstructCall() ? constructTrap : callTrap, | |
| 71 this, arguments, 0, %_ArgumentsLength()) | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 function DerivedGetTrap(receiver, name) { | |
| 76 var desc = this.getPropertyDescriptor(name) | |
| 77 if (IS_UNDEFINED(desc)) { return desc } | |
| 78 if ('value' in desc) { | |
| 79 return desc.value | |
| 80 } else { | |
| 81 if (IS_UNDEFINED(desc.get)) { return desc.get } | |
| 82 // The proposal says: desc.get.call(receiver) | |
| 83 return %_CallFunction(receiver, desc.get) | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 function DerivedSetTrap(receiver, name, val) { | |
| 88 var desc = this.getOwnPropertyDescriptor(name) | |
| 89 if (desc) { | |
| 90 if ('writable' in desc) { | |
| 91 if (desc.writable) { | |
| 92 desc.value = val | |
| 93 this.defineProperty(name, desc) | |
| 94 return true | |
| 95 } else { | |
| 96 return false | |
| 97 } | |
| 98 } else { // accessor | |
| 99 if (desc.set) { | |
| 100 // The proposal says: desc.set.call(receiver, val) | |
| 101 %_CallFunction(receiver, val, desc.set) | |
| 102 return true | |
| 103 } else { | |
| 104 return false | |
| 105 } | |
| 106 } | |
| 107 } | |
| 108 desc = this.getPropertyDescriptor(name) | |
| 109 if (desc) { | |
| 110 if ('writable' in desc) { | |
| 111 if (desc.writable) { | |
| 112 // fall through | |
| 113 } else { | |
| 114 return false | |
| 115 } | |
| 116 } else { // accessor | |
| 117 if (desc.set) { | |
| 118 // The proposal says: desc.set.call(receiver, val) | |
| 119 %_CallFunction(receiver, val, desc.set) | |
| 120 return true | |
| 121 } else { | |
| 122 return false | |
| 123 } | |
| 124 } | |
| 125 } | |
| 126 this.defineProperty(name, { | |
| 127 value: val, | |
| 128 writable: true, | |
| 129 enumerable: true, | |
| 130 configurable: true}); | |
| 131 return true; | |
| 132 } | |
| 133 | |
| 134 function DerivedHasTrap(name) { | |
| 135 return !!this.getPropertyDescriptor(name) | |
| 136 } | |
| 137 | |
| 138 function DerivedHasOwnTrap(name) { | |
| 139 return !!this.getOwnPropertyDescriptor(name) | |
| 140 } | |
| 141 | |
| 142 function DerivedKeysTrap() { | |
| 143 var names = this.getOwnPropertyNames() | |
| 144 var enumerableNames = [] | |
| 145 for (var i = 0, count = 0; i < names.length; ++i) { | |
| 146 var name = names[i] | |
| 147 if (IS_SYMBOL(name)) continue | |
| 148 var desc = this.getOwnPropertyDescriptor(TO_STRING(name)) | |
| 149 if (!IS_UNDEFINED(desc) && desc.enumerable) { | |
| 150 enumerableNames[count++] = names[i] | |
| 151 } | |
| 152 } | |
| 153 return enumerableNames | |
| 154 } | |
| 155 | |
| 156 function DerivedEnumerateTrap() { | |
| 157 var names = this.getPropertyNames() | |
| 158 var enumerableNames = [] | |
| 159 for (var i = 0, count = 0; i < names.length; ++i) { | |
| 160 var name = names[i] | |
| 161 if (IS_SYMBOL(name)) continue | |
| 162 var desc = this.getPropertyDescriptor(TO_STRING(name)) | |
| 163 if (!IS_UNDEFINED(desc)) { | |
| 164 if (!desc.configurable) { | |
| 165 throw MakeTypeError(kProxyPropNotConfigurable, | |
| 166 this, name, "getPropertyDescriptor") | |
| 167 } | |
| 168 if (desc.enumerable) enumerableNames[count++] = names[i] | |
| 169 } | |
| 170 } | |
| 171 return enumerableNames | |
| 172 } | |
| 173 | |
| 174 function ProxyEnumerate(proxy) { | |
| 175 var handler = %GetHandler(proxy) | |
| 176 if (IS_UNDEFINED(handler.enumerate)) { | |
| 177 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0) | |
| 178 } else { | |
| 179 return ToNameArray(handler.enumerate(), "enumerate", false) | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 //------------------------------------------------------------------- | |
| 184 | |
| 185 var Proxy = new GlobalObject(); | |
| 186 %AddNamedProperty(global, "Proxy", Proxy, DONT_ENUM); | |
| 187 | |
| 188 //Set up non-enumerable properties of the Proxy object. | |
| 189 utils.InstallFunctions(Proxy, DONT_ENUM, [ | |
| 190 "create", ProxyCreate, | |
| 191 "createFunction", ProxyCreateFunction | |
| 192 ]) | |
| 193 | |
| 194 // ------------------------------------------------------------------- | |
| 195 // Exports | |
| 196 | |
| 197 utils.Export(function(to) { | |
| 198 to.ProxyDelegateCallAndConstruct = DelegateCallAndConstruct; | |
| 199 to.ProxyDerivedHasOwnTrap = DerivedHasOwnTrap; | |
| 200 to.ProxyDerivedKeysTrap = DerivedKeysTrap; | |
| 201 }); | |
| 202 | |
| 203 %InstallToContext([ | |
| 204 "derived_get_trap", DerivedGetTrap, | |
| 205 "derived_has_trap", DerivedHasTrap, | |
| 206 "derived_set_trap", DerivedSetTrap, | |
| 207 "proxy_enumerate", ProxyEnumerate, | |
| 208 ]); | |
| 209 | |
| 210 }) | |
| OLD | NEW |