blob: 4e86c8892a3c8d08ef966f70d8485de50a5f10fd [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
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000034$Proxy.create = function(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
lrn@chromium.org34e60782011-09-15 07:25:40 +000044$Proxy.createFunction = function(handler, callTrap, constructTrap) {
45 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
65
66
67////////////////////////////////////////////////////////////////////////////////
68// Builtins
69////////////////////////////////////////////////////////////////////////////////
70
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000071function DerivedConstructTrap(callTrap) {
72 return function() {
73 var proto = this.prototype
74 if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
75 var obj = new $Object()
76 obj.__proto__ = proto
77 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
78 return IS_SPEC_OBJECT(result) ? result : obj
79 }
80}
81
lrn@chromium.org34e60782011-09-15 07:25:40 +000082function DelegateCallAndConstruct(callTrap, constructTrap) {
83 return function() {
84 return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
85 this, arguments, 0, %_ArgumentsLength())
86 }
87}
88
ager@chromium.orgea91cc52011-05-23 06:06:11 +000089function DerivedGetTrap(receiver, name) {
90 var desc = this.getPropertyDescriptor(name)
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000091 if (IS_UNDEFINED(desc)) { return desc }
ager@chromium.orgea91cc52011-05-23 06:06:11 +000092 if ('value' in desc) {
93 return desc.value
94 } else {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000095 if (IS_UNDEFINED(desc.get)) { return desc.get }
96 // The proposal says: desc.get.call(receiver)
97 return %_CallFunction(receiver, desc.get)
ager@chromium.orgea91cc52011-05-23 06:06:11 +000098 }
99}
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000100
101function DerivedSetTrap(receiver, name, val) {
102 var desc = this.getOwnPropertyDescriptor(name)
103 if (desc) {
104 if ('writable' in desc) {
105 if (desc.writable) {
106 desc.value = val
107 this.defineProperty(name, desc)
108 return true
109 } else {
110 return false
111 }
112 } else { // accessor
113 if (desc.set) {
114 // The proposal says: desc.set.call(receiver, val)
115 %_CallFunction(receiver, val, desc.set)
116 return true
117 } else {
118 return false
119 }
120 }
121 }
122 desc = this.getPropertyDescriptor(name)
123 if (desc) {
124 if ('writable' in desc) {
125 if (desc.writable) {
126 // fall through
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 this.defineProperty(name, {
141 value: val,
142 writable: true,
143 enumerable: true,
144 configurable: true});
145 return true;
146}
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000147
148function DerivedHasTrap(name) {
149 return !!this.getPropertyDescriptor(name)
150}
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000151
ricow@chromium.org9fa09672011-07-25 11:05:35 +0000152function DerivedHasOwnTrap(name) {
153 return !!this.getOwnPropertyDescriptor(name)
154}
155
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000156function DerivedKeysTrap() {
157 var names = this.getOwnPropertyNames()
158 var enumerableNames = []
159 for (var i = 0, count = 0; i < names.length; ++i) {
160 var name = names[i]
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000161 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
162 if (!IS_UNDEFINED(desc) && desc.enumerable) {
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000163 enumerableNames[count++] = names[i]
164 }
165 }
166 return enumerableNames
167}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000168
169function DerivedEnumerateTrap() {
170 var names = this.getPropertyNames()
171 var enumerableNames = []
172 for (var i = 0, count = 0; i < names.length; ++i) {
173 var name = names[i]
174 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
175 if (!IS_UNDEFINED(desc) && desc.enumerable) {
176 enumerableNames[count++] = names[i]
177 }
178 }
179 return enumerableNames
180}
181
182function ProxyEnumerate(proxy) {
183 var handler = %GetHandler(proxy)
184 if (IS_UNDEFINED(handler.enumerate)) {
185 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
186 } else {
187 return ToStringArray(handler.enumerate(), "enumerate")
188 }
189}