Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1 | // Copyright 2011 the V8 project authors. All rights reserved. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 4 | |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 5 | "use strict"; |
| 6 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 7 | // This file relies on the fact that the following declaration has been made |
| 8 | // in runtime.js: |
| 9 | // var $Object = global.Object; |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 10 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 11 | var $Proxy = new $Object(); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 12 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 13 | // ------------------------------------------------------------------- |
| 14 | |
| 15 | function ProxyCreate(handler, proto) { |
Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 16 | if (!IS_SPEC_OBJECT(handler)) |
| 17 | throw MakeTypeError("handler_non_object", ["create"]) |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 18 | if (IS_UNDEFINED(proto)) |
| 19 | proto = null |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 20 | else if (!(IS_SPEC_OBJECT(proto) || IS_NULL(proto))) |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 21 | throw MakeTypeError("proto_non_object", ["create"]) |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 22 | return %CreateJSProxy(handler, proto) |
| 23 | } |
| 24 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 25 | function ProxyCreateFunction(handler, callTrap, constructTrap) { |
Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 26 | if (!IS_SPEC_OBJECT(handler)) |
| 27 | throw MakeTypeError("handler_non_object", ["create"]) |
| 28 | if (!IS_SPEC_FUNCTION(callTrap)) |
| 29 | throw MakeTypeError("trap_function_expected", ["createFunction", "call"]) |
| 30 | if (IS_UNDEFINED(constructTrap)) { |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 31 | constructTrap = DerivedConstructTrap(callTrap) |
| 32 | } else if (IS_SPEC_FUNCTION(constructTrap)) { |
| 33 | // Make sure the trap receives 'undefined' as this. |
| 34 | var construct = constructTrap |
| 35 | constructTrap = function() { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 36 | return %Apply(construct, UNDEFINED, arguments, 0, %_ArgumentsLength()); |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 37 | } |
| 38 | } else { |
Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 39 | throw MakeTypeError("trap_function_expected", |
| 40 | ["createFunction", "construct"]) |
| 41 | } |
| 42 | return %CreateJSFunctionProxy( |
| 43 | handler, callTrap, constructTrap, $Function.prototype) |
| 44 | } |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 45 | |
| 46 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 47 | // ------------------------------------------------------------------- |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 48 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 49 | function SetUpProxy() { |
| 50 | %CheckIsBootstrapping() |
| 51 | |
| 52 | var global_proxy = %GlobalProxy(global); |
| 53 | global_proxy.Proxy = $Proxy; |
| 54 | |
| 55 | // Set up non-enumerable properties of the Proxy object. |
| 56 | InstallFunctions($Proxy, DONT_ENUM, [ |
| 57 | "create", ProxyCreate, |
| 58 | "createFunction", ProxyCreateFunction |
| 59 | ]) |
| 60 | } |
| 61 | |
| 62 | SetUpProxy(); |
| 63 | |
| 64 | |
| 65 | // ------------------------------------------------------------------- |
| 66 | // Proxy Builtins |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 67 | |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 68 | function DerivedConstructTrap(callTrap) { |
| 69 | return function() { |
| 70 | var proto = this.prototype |
| 71 | if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 72 | var obj = { __proto__: proto }; |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 73 | var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength()); |
| 74 | return IS_SPEC_OBJECT(result) ? result : obj |
| 75 | } |
| 76 | } |
| 77 | |
Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 78 | function DelegateCallAndConstruct(callTrap, constructTrap) { |
| 79 | return function() { |
| 80 | return %Apply(%_IsConstructCall() ? constructTrap : callTrap, |
| 81 | this, arguments, 0, %_ArgumentsLength()) |
| 82 | } |
| 83 | } |
| 84 | |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 85 | function DerivedGetTrap(receiver, name) { |
| 86 | var desc = this.getPropertyDescriptor(name) |
Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 87 | if (IS_UNDEFINED(desc)) { return desc } |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 88 | if ('value' in desc) { |
| 89 | return desc.value |
| 90 | } else { |
Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 91 | if (IS_UNDEFINED(desc.get)) { return desc.get } |
| 92 | // The proposal says: desc.get.call(receiver) |
| 93 | return %_CallFunction(receiver, desc.get) |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 94 | } |
| 95 | } |
Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 96 | |
| 97 | function DerivedSetTrap(receiver, name, val) { |
| 98 | var desc = this.getOwnPropertyDescriptor(name) |
| 99 | if (desc) { |
| 100 | if ('writable' in desc) { |
| 101 | if (desc.writable) { |
| 102 | desc.value = val |
| 103 | this.defineProperty(name, desc) |
| 104 | return true |
| 105 | } else { |
| 106 | return false |
| 107 | } |
| 108 | } else { // accessor |
| 109 | if (desc.set) { |
| 110 | // The proposal says: desc.set.call(receiver, val) |
| 111 | %_CallFunction(receiver, val, desc.set) |
| 112 | return true |
| 113 | } else { |
| 114 | return false |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | desc = this.getPropertyDescriptor(name) |
| 119 | if (desc) { |
| 120 | if ('writable' in desc) { |
| 121 | if (desc.writable) { |
| 122 | // fall through |
| 123 | } else { |
| 124 | return false |
| 125 | } |
| 126 | } else { // accessor |
| 127 | if (desc.set) { |
| 128 | // The proposal says: desc.set.call(receiver, val) |
| 129 | %_CallFunction(receiver, val, desc.set) |
| 130 | return true |
| 131 | } else { |
| 132 | return false |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | this.defineProperty(name, { |
| 137 | value: val, |
| 138 | writable: true, |
| 139 | enumerable: true, |
| 140 | configurable: true}); |
| 141 | return true; |
| 142 | } |
| 143 | |
| 144 | function DerivedHasTrap(name) { |
| 145 | return !!this.getPropertyDescriptor(name) |
| 146 | } |
| 147 | |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 148 | function DerivedHasOwnTrap(name) { |
| 149 | return !!this.getOwnPropertyDescriptor(name) |
| 150 | } |
| 151 | |
Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 152 | function DerivedKeysTrap() { |
| 153 | var names = this.getOwnPropertyNames() |
| 154 | var enumerableNames = [] |
| 155 | for (var i = 0, count = 0; i < names.length; ++i) { |
| 156 | var name = names[i] |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 157 | if (IS_SYMBOL(name)) continue |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 158 | var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name)) |
| 159 | if (!IS_UNDEFINED(desc) && desc.enumerable) { |
Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 160 | enumerableNames[count++] = names[i] |
| 161 | } |
| 162 | } |
| 163 | return enumerableNames |
| 164 | } |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 165 | |
| 166 | function DerivedEnumerateTrap() { |
| 167 | var names = this.getPropertyNames() |
| 168 | var enumerableNames = [] |
| 169 | for (var i = 0, count = 0; i < names.length; ++i) { |
| 170 | var name = names[i] |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 171 | if (IS_SYMBOL(name)) continue |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 172 | var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name)) |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 173 | if (!IS_UNDEFINED(desc)) { |
| 174 | if (!desc.configurable) { |
| 175 | throw MakeTypeError("proxy_prop_not_configurable", |
| 176 | [this, "getPropertyDescriptor", name]) |
| 177 | } |
| 178 | if (desc.enumerable) enumerableNames[count++] = names[i] |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 179 | } |
| 180 | } |
| 181 | return enumerableNames |
| 182 | } |
| 183 | |
| 184 | function ProxyEnumerate(proxy) { |
| 185 | var handler = %GetHandler(proxy) |
| 186 | if (IS_UNDEFINED(handler.enumerate)) { |
| 187 | return %Apply(DerivedEnumerateTrap, handler, [], 0, 0) |
| 188 | } else { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 189 | return ToNameArray(handler.enumerate(), "enumerate", false) |
Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 190 | } |
| 191 | } |