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.
5 (function(global, utils) {
9 %CheckIsBootstrapping();
11 // ----------------------------------------------------------------------------
14 var GlobalFunction = global.Function;
15 var GlobalObject = global.Object;
19 utils.Import(function(from) {
20 ToNameArray = from.ToNameArray;
23 //----------------------------------------------------------------------------
25 function ProxyCreate(handler, proto) {
26 if (!IS_SPEC_OBJECT(handler))
27 throw MakeTypeError(kProxyHandlerNonObject, "create")
28 if (IS_UNDEFINED(proto))
30 else if (!(IS_SPEC_OBJECT(proto) || IS_NULL(proto)))
31 throw MakeTypeError(kProxyProtoNonObject)
32 return %CreateJSProxy(handler, proto)
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());
49 throw MakeTypeError(kProxyTrapFunctionExpected, "construct")
51 return %CreateJSFunctionProxy(
52 handler, callTrap, constructTrap, GlobalFunction.prototype)
55 // -------------------------------------------------------------------
58 function DerivedConstructTrap(callTrap) {
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
68 function DelegateCallAndConstruct(callTrap, constructTrap) {
70 return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
71 this, arguments, 0, %_ArgumentsLength())
75 function DerivedGetTrap(receiver, name) {
76 var desc = this.getPropertyDescriptor(name)
77 if (IS_UNDEFINED(desc)) { return desc }
78 if ('value' in desc) {
81 if (IS_UNDEFINED(desc.get)) { return desc.get }
82 // The proposal says: desc.get.call(receiver)
83 return %_CallFunction(receiver, desc.get)
87 function DerivedSetTrap(receiver, name, val) {
88 var desc = this.getOwnPropertyDescriptor(name)
90 if ('writable' in desc) {
93 this.defineProperty(name, desc)
100 // The proposal says: desc.set.call(receiver, val)
101 %_CallFunction(receiver, val, desc.set)
108 desc = this.getPropertyDescriptor(name)
110 if ('writable' in desc) {
118 // The proposal says: desc.set.call(receiver, val)
119 %_CallFunction(receiver, val, desc.set)
126 this.defineProperty(name, {
130 configurable: true});
134 function DerivedHasTrap(name) {
135 return !!this.getPropertyDescriptor(name)
138 function DerivedHasOwnTrap(name) {
139 return !!this.getOwnPropertyDescriptor(name)
142 function DerivedKeysTrap() {
143 var names = this.getOwnPropertyNames()
144 var enumerableNames = []
145 for (var i = 0, count = 0; i < names.length; ++i) {
147 if (IS_SYMBOL(name)) continue
148 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
149 if (!IS_UNDEFINED(desc) && desc.enumerable) {
150 enumerableNames[count++] = names[i]
153 return enumerableNames
156 function DerivedEnumerateTrap() {
157 var names = this.getPropertyNames()
158 var enumerableNames = []
159 for (var i = 0, count = 0; i < names.length; ++i) {
161 if (IS_SYMBOL(name)) continue
162 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
163 if (!IS_UNDEFINED(desc)) {
164 if (!desc.configurable) {
165 throw MakeTypeError(kProxyPropNotConfigurable,
166 this, name, "getPropertyDescriptor")
168 if (desc.enumerable) enumerableNames[count++] = names[i]
171 return enumerableNames
174 function ProxyEnumerate(proxy) {
175 var handler = %GetHandler(proxy)
176 if (IS_UNDEFINED(handler.enumerate)) {
177 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
179 return ToNameArray(handler.enumerate(), "enumerate", false)
183 //-------------------------------------------------------------------
185 var Proxy = new GlobalObject();
186 %AddNamedProperty(global, "Proxy", Proxy, DONT_ENUM);
188 //Set up non-enumerable properties of the Proxy object.
189 utils.InstallFunctions(Proxy, DONT_ENUM, [
190 "create", ProxyCreate,
191 "createFunction", ProxyCreateFunction
194 // -------------------------------------------------------------------
197 utils.Export(function(to) {
198 to.ProxyDelegateCallAndConstruct = DelegateCallAndConstruct;
199 to.ProxyDerivedHasOwnTrap = DerivedHasOwnTrap;
200 to.ProxyDerivedKeysTrap = DerivedKeysTrap;
204 "derived_get_trap", DerivedGetTrap,
205 "derived_has_trap", DerivedHasTrap,
206 "derived_set_trap", DerivedSetTrap,
207 "proxy_enumerate", ProxyEnumerate,