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 |