Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / proxy.js
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 "use strict";
6
7 // This file relies on the fact that the following declaration has been made
8 // in runtime.js:
9 // var $Object = global.Object;
10
11 var $Proxy = new $Object();
12
13 // -------------------------------------------------------------------
14
15 function ProxyCreate(handler, proto) {
16   if (!IS_SPEC_OBJECT(handler))
17     throw MakeTypeError("handler_non_object", ["create"])
18   if (IS_UNDEFINED(proto))
19     proto = null
20   else if (!(IS_SPEC_OBJECT(proto) || IS_NULL(proto)))
21     throw MakeTypeError("proto_non_object", ["create"])
22   return %CreateJSProxy(handler, proto)
23 }
24
25 function ProxyCreateFunction(handler, callTrap, constructTrap) {
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)) {
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() {
36       return %Apply(construct, UNDEFINED, arguments, 0, %_ArgumentsLength());
37     }
38   } else {
39     throw MakeTypeError("trap_function_expected",
40                         ["createFunction", "construct"])
41   }
42   return %CreateJSFunctionProxy(
43     handler, callTrap, constructTrap, $Function.prototype)
44 }
45
46
47 // -------------------------------------------------------------------
48
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
67
68 function DerivedConstructTrap(callTrap) {
69   return function() {
70     var proto = this.prototype
71     if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
72     var obj = { __proto__: proto };
73     var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
74     return IS_SPEC_OBJECT(result) ? result : obj
75   }
76 }
77
78 function DelegateCallAndConstruct(callTrap, constructTrap) {
79   return function() {
80     return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
81                   this, arguments, 0, %_ArgumentsLength())
82   }
83 }
84
85 function DerivedGetTrap(receiver, name) {
86   var desc = this.getPropertyDescriptor(name)
87   if (IS_UNDEFINED(desc)) { return desc }
88   if ('value' in desc) {
89     return desc.value
90   } else {
91     if (IS_UNDEFINED(desc.get)) { return desc.get }
92     // The proposal says: desc.get.call(receiver)
93     return %_CallFunction(receiver, desc.get)
94   }
95 }
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
148 function DerivedHasOwnTrap(name) {
149   return !!this.getOwnPropertyDescriptor(name)
150 }
151
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]
157     if (IS_SYMBOL(name)) continue
158     var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
159     if (!IS_UNDEFINED(desc) && desc.enumerable) {
160       enumerableNames[count++] = names[i]
161     }
162   }
163   return enumerableNames
164 }
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]
171     if (IS_SYMBOL(name)) continue
172     var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
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]
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 {
189     return ToNameArray(handler.enumerate(), "enumerate", false)
190   }
191 }