blob: 528c47d80dcda3a3fbab317ce0cc34ed05b83905 [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
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000030// This file relies on the fact that the following declaration has been made
31// in runtime.js:
32// var $Object = global.Object;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000033
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000034var $Proxy = new $Object();
35
36// -------------------------------------------------------------------
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000037
danno@chromium.org72204d52012-10-31 10:02:10 +000038function ProxyCreate(handler, proto) {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000039 if (!IS_SPEC_OBJECT(handler))
40 throw MakeTypeError("handler_non_object", ["create"])
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000041 if (IS_UNDEFINED(proto))
42 proto = null
43 else if (!(IS_SPEC_OBJECT(proto) || proto === null))
44 throw MakeTypeError("proto_non_object", ["create"])
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000045 return %CreateJSProxy(handler, proto)
46}
ager@chromium.orgea91cc52011-05-23 06:06:11 +000047
danno@chromium.org72204d52012-10-31 10:02:10 +000048function ProxyCreateFunction(handler, callTrap, constructTrap) {
lrn@chromium.org34e60782011-09-15 07:25:40 +000049 if (!IS_SPEC_OBJECT(handler))
50 throw MakeTypeError("handler_non_object", ["create"])
51 if (!IS_SPEC_FUNCTION(callTrap))
52 throw MakeTypeError("trap_function_expected", ["createFunction", "call"])
53 if (IS_UNDEFINED(constructTrap)) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000054 constructTrap = DerivedConstructTrap(callTrap)
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000055 } else if (IS_SPEC_FUNCTION(constructTrap)) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000056 // Make sure the trap receives 'undefined' as this.
57 var construct = constructTrap
58 constructTrap = function() {
59 return %Apply(construct, void 0, arguments, 0, %_ArgumentsLength());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000060 }
61 } else {
lrn@chromium.org34e60782011-09-15 07:25:40 +000062 throw MakeTypeError("trap_function_expected",
63 ["createFunction", "construct"])
64 }
65 return %CreateJSFunctionProxy(
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000066 handler, callTrap, constructTrap, $Function.prototype)
lrn@chromium.org34e60782011-09-15 07:25:40 +000067}
ager@chromium.orgea91cc52011-05-23 06:06:11 +000068
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000069
70// -------------------------------------------------------------------
71
72function SetUpProxy() {
73 %CheckIsBootstrapping()
74
75 global.Proxy = $Proxy;
76
77 // Set up non-enumerable properties of the Proxy object.
78 InstallFunctions($Proxy, DONT_ENUM, [
79 "create", ProxyCreate,
80 "createFunction", ProxyCreateFunction
81 ])
82}
83
84SetUpProxy();
ager@chromium.orgea91cc52011-05-23 06:06:11 +000085
86
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000087// -------------------------------------------------------------------
88// Proxy Builtins
ager@chromium.orgea91cc52011-05-23 06:06:11 +000089
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000090function DerivedConstructTrap(callTrap) {
91 return function() {
92 var proto = this.prototype
93 if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
ulan@chromium.org750145a2013-03-07 15:14:13 +000094 var obj = { __proto__: proto };
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000095 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
96 return IS_SPEC_OBJECT(result) ? result : obj
97 }
98}
99
lrn@chromium.org34e60782011-09-15 07:25:40 +0000100function DelegateCallAndConstruct(callTrap, constructTrap) {
101 return function() {
102 return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
103 this, arguments, 0, %_ArgumentsLength())
104 }
105}
106
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000107function DerivedGetTrap(receiver, name) {
108 var desc = this.getPropertyDescriptor(name)
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000109 if (IS_UNDEFINED(desc)) { return desc }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000110 if ('value' in desc) {
111 return desc.value
112 } else {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000113 if (IS_UNDEFINED(desc.get)) { return desc.get }
114 // The proposal says: desc.get.call(receiver)
115 return %_CallFunction(receiver, desc.get)
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000116 }
117}
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000118
119function DerivedSetTrap(receiver, name, val) {
120 var desc = this.getOwnPropertyDescriptor(name)
121 if (desc) {
122 if ('writable' in desc) {
123 if (desc.writable) {
124 desc.value = val
125 this.defineProperty(name, desc)
126 return true
127 } else {
128 return false
129 }
130 } else { // accessor
131 if (desc.set) {
132 // The proposal says: desc.set.call(receiver, val)
133 %_CallFunction(receiver, val, desc.set)
134 return true
135 } else {
136 return false
137 }
138 }
139 }
140 desc = this.getPropertyDescriptor(name)
141 if (desc) {
142 if ('writable' in desc) {
143 if (desc.writable) {
144 // fall through
145 } else {
146 return false
147 }
148 } else { // accessor
149 if (desc.set) {
150 // The proposal says: desc.set.call(receiver, val)
151 %_CallFunction(receiver, val, desc.set)
152 return true
153 } else {
154 return false
155 }
156 }
157 }
158 this.defineProperty(name, {
159 value: val,
160 writable: true,
161 enumerable: true,
162 configurable: true});
163 return true;
164}
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000165
166function DerivedHasTrap(name) {
167 return !!this.getPropertyDescriptor(name)
168}
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000169
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000170function DerivedHasOwnTrap(name) {
171 return !!this.getOwnPropertyDescriptor(name)
172}
173
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000174function DerivedKeysTrap() {
175 var names = this.getOwnPropertyNames()
176 var enumerableNames = []
177 for (var i = 0, count = 0; i < names.length; ++i) {
178 var name = names[i]
ulan@chromium.org750145a2013-03-07 15:14:13 +0000179 if (IS_SYMBOL(name)) continue
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000180 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
181 if (!IS_UNDEFINED(desc) && desc.enumerable) {
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000182 enumerableNames[count++] = names[i]
183 }
184 }
185 return enumerableNames
186}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000187
188function DerivedEnumerateTrap() {
189 var names = this.getPropertyNames()
190 var enumerableNames = []
191 for (var i = 0, count = 0; i < names.length; ++i) {
192 var name = names[i]
ulan@chromium.org750145a2013-03-07 15:14:13 +0000193 if (IS_SYMBOL(name)) continue
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000194 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
195 if (!IS_UNDEFINED(desc) && desc.enumerable) {
196 enumerableNames[count++] = names[i]
197 }
198 }
199 return enumerableNames
200}
201
202function ProxyEnumerate(proxy) {
203 var handler = %GetHandler(proxy)
204 if (IS_UNDEFINED(handler.enumerate)) {
205 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
206 } else {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000207 return ToNameArray(handler.enumerate(), "enumerate", false)
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000208 }
209}