blob: 53a35724748b56e4c147b83918f5ca8283045e8c [file] [log] [blame]
danno@chromium.org160a7b02011-04-18 15:51:38 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000028"use strict";
29
danno@chromium.org160a7b02011-04-18 15:51:38 +000030global.Proxy = new $Object();
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000031
32var $Proxy = global.Proxy
33
danno@chromium.org72204d52012-10-31 10:02:10 +000034function ProxyCreate(handler, proto) {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000035 if (!IS_SPEC_OBJECT(handler))
36 throw MakeTypeError("handler_non_object", ["create"])
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000037 if (IS_UNDEFINED(proto))
38 proto = null
39 else if (!(IS_SPEC_OBJECT(proto) || proto === null))
40 throw MakeTypeError("proto_non_object", ["create"])
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000041 return %CreateJSProxy(handler, proto)
42}
ager@chromium.orgea91cc52011-05-23 06:06:11 +000043
danno@chromium.org72204d52012-10-31 10:02:10 +000044function ProxyCreateFunction(handler, callTrap, constructTrap) {
lrn@chromium.org34e60782011-09-15 07:25:40 +000045 if (!IS_SPEC_OBJECT(handler))
46 throw MakeTypeError("handler_non_object", ["create"])
47 if (!IS_SPEC_FUNCTION(callTrap))
48 throw MakeTypeError("trap_function_expected", ["createFunction", "call"])
49 if (IS_UNDEFINED(constructTrap)) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000050 constructTrap = DerivedConstructTrap(callTrap)
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000051 } else if (IS_SPEC_FUNCTION(constructTrap)) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000052 // Make sure the trap receives 'undefined' as this.
53 var construct = constructTrap
54 constructTrap = function() {
55 return %Apply(construct, void 0, arguments, 0, %_ArgumentsLength());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000056 }
57 } else {
lrn@chromium.org34e60782011-09-15 07:25:40 +000058 throw MakeTypeError("trap_function_expected",
59 ["createFunction", "construct"])
60 }
61 return %CreateJSFunctionProxy(
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000062 handler, callTrap, constructTrap, $Function.prototype)
lrn@chromium.org34e60782011-09-15 07:25:40 +000063}
ager@chromium.orgea91cc52011-05-23 06:06:11 +000064
danno@chromium.org72204d52012-10-31 10:02:10 +000065%CheckIsBootstrapping()
66InstallFunctions($Proxy, DONT_ENUM, [
67 "create", ProxyCreate,
68 "createFunction", ProxyCreateFunction
69])
ager@chromium.orgea91cc52011-05-23 06:06:11 +000070
71
72////////////////////////////////////////////////////////////////////////////////
73// Builtins
74////////////////////////////////////////////////////////////////////////////////
75
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000076function DerivedConstructTrap(callTrap) {
77 return function() {
78 var proto = this.prototype
79 if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
80 var obj = new $Object()
81 obj.__proto__ = proto
82 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
83 return IS_SPEC_OBJECT(result) ? result : obj
84 }
85}
86
lrn@chromium.org34e60782011-09-15 07:25:40 +000087function DelegateCallAndConstruct(callTrap, constructTrap) {
88 return function() {
89 return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
90 this, arguments, 0, %_ArgumentsLength())
91 }
92}
93
ager@chromium.orgea91cc52011-05-23 06:06:11 +000094function DerivedGetTrap(receiver, name) {
95 var desc = this.getPropertyDescriptor(name)
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000096 if (IS_UNDEFINED(desc)) { return desc }
ager@chromium.orgea91cc52011-05-23 06:06:11 +000097 if ('value' in desc) {
98 return desc.value
99 } else {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000100 if (IS_UNDEFINED(desc.get)) { return desc.get }
101 // The proposal says: desc.get.call(receiver)
102 return %_CallFunction(receiver, desc.get)
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000103 }
104}
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000105
106function DerivedSetTrap(receiver, name, val) {
107 var desc = this.getOwnPropertyDescriptor(name)
108 if (desc) {
109 if ('writable' in desc) {
110 if (desc.writable) {
111 desc.value = val
112 this.defineProperty(name, desc)
113 return true
114 } else {
115 return false
116 }
117 } else { // accessor
118 if (desc.set) {
119 // The proposal says: desc.set.call(receiver, val)
120 %_CallFunction(receiver, val, desc.set)
121 return true
122 } else {
123 return false
124 }
125 }
126 }
127 desc = this.getPropertyDescriptor(name)
128 if (desc) {
129 if ('writable' in desc) {
130 if (desc.writable) {
131 // fall through
132 } else {
133 return false
134 }
135 } else { // accessor
136 if (desc.set) {
137 // The proposal says: desc.set.call(receiver, val)
138 %_CallFunction(receiver, val, desc.set)
139 return true
140 } else {
141 return false
142 }
143 }
144 }
145 this.defineProperty(name, {
146 value: val,
147 writable: true,
148 enumerable: true,
149 configurable: true});
150 return true;
151}
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000152
153function DerivedHasTrap(name) {
154 return !!this.getPropertyDescriptor(name)
155}
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000156
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000157function DerivedHasOwnTrap(name) {
158 return !!this.getOwnPropertyDescriptor(name)
159}
160
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000161function DerivedKeysTrap() {
162 var names = this.getOwnPropertyNames()
163 var enumerableNames = []
164 for (var i = 0, count = 0; i < names.length; ++i) {
165 var name = names[i]
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000166 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
167 if (!IS_UNDEFINED(desc) && desc.enumerable) {
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000168 enumerableNames[count++] = names[i]
169 }
170 }
171 return enumerableNames
172}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000173
174function DerivedEnumerateTrap() {
175 var names = this.getPropertyNames()
176 var enumerableNames = []
177 for (var i = 0, count = 0; i < names.length; ++i) {
178 var name = names[i]
179 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
180 if (!IS_UNDEFINED(desc) && desc.enumerable) {
181 enumerableNames[count++] = names[i]
182 }
183 }
184 return enumerableNames
185}
186
187function ProxyEnumerate(proxy) {
188 var handler = %GetHandler(proxy)
189 if (IS_UNDEFINED(handler.enumerate)) {
190 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
191 } else {
192 return ToStringArray(handler.enumerate(), "enumerate")
193 }
194}